1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * Alpha emulation cpu translation for qemu.
3fcf5ef2aSThomas Huth *
4fcf5ef2aSThomas Huth * Copyright (c) 2007 Jocelyn Mayer
5fcf5ef2aSThomas Huth *
6fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or
7fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public
8fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either
9d6ea4236SChetan Pant * version 2.1 of the License, or (at your option) any later version.
10fcf5ef2aSThomas Huth *
11fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful,
12fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14fcf5ef2aSThomas Huth * Lesser General Public License for more details.
15fcf5ef2aSThomas Huth *
16fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public
17fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18fcf5ef2aSThomas Huth */
19fcf5ef2aSThomas Huth
20fcf5ef2aSThomas Huth #include "qemu/osdep.h"
21fcf5ef2aSThomas Huth #include "cpu.h"
22d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
23fcf5ef2aSThomas Huth #include "qemu/host-utils.h"
24fcf5ef2aSThomas Huth #include "exec/exec-all.h"
25dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
26fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
27fcf5ef2aSThomas Huth #include "exec/helper-gen.h"
283de811c6SRichard Henderson #include "exec/translator.h"
29fcf5ef2aSThomas Huth #include "exec/log.h"
30fcf5ef2aSThomas Huth
31d53106c9SRichard Henderson #define HELPER_H "helper.h"
32d53106c9SRichard Henderson #include "exec/helper-info.c.inc"
33d53106c9SRichard Henderson #undef HELPER_H
34fcf5ef2aSThomas Huth
35fcf5ef2aSThomas Huth #undef ALPHA_DEBUG_DISAS
36fcf5ef2aSThomas Huth #define CONFIG_SOFTFLOAT_INLINE
37fcf5ef2aSThomas Huth
38fcf5ef2aSThomas Huth #ifdef ALPHA_DEBUG_DISAS
39fcf5ef2aSThomas Huth # define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
40fcf5ef2aSThomas Huth #else
41fcf5ef2aSThomas Huth # define LOG_DISAS(...) do { } while (0)
42fcf5ef2aSThomas Huth #endif
43fcf5ef2aSThomas Huth
44fcf5ef2aSThomas Huth typedef struct DisasContext DisasContext;
45fcf5ef2aSThomas Huth struct DisasContext {
46c5f80657SRichard Henderson DisasContextBase base;
47c5f80657SRichard Henderson
48fed14246SRichard Henderson #ifdef CONFIG_USER_ONLY
49fed14246SRichard Henderson MemOp unalign;
50fed14246SRichard Henderson #else
51fcf5ef2aSThomas Huth uint64_t palbr;
52fcf5ef2aSThomas Huth #endif
53489a0e64SRichard Henderson uint32_t tbflags;
54fcf5ef2aSThomas Huth int mem_idx;
55fcf5ef2aSThomas Huth
56*23bb0863SRichard Henderson /* True if generating pc-relative code. */
57*23bb0863SRichard Henderson bool pcrel;
58*23bb0863SRichard Henderson
59c6d41b36SRichard Henderson /* implver and amask values for this CPU. */
60c6d41b36SRichard Henderson int implver;
61c6d41b36SRichard Henderson int amask;
62c6d41b36SRichard Henderson
63fcf5ef2aSThomas Huth /* Current rounding mode for this TB. */
64fcf5ef2aSThomas Huth int tb_rm;
65fcf5ef2aSThomas Huth /* Current flush-to-zero setting for this TB. */
66fcf5ef2aSThomas Huth int tb_ftz;
67fcf5ef2aSThomas Huth
68fcf5ef2aSThomas Huth /* The set of registers active in the current context. */
69fcf5ef2aSThomas Huth TCGv *ir;
70fcf5ef2aSThomas Huth
71fcf5ef2aSThomas Huth /* Temporaries for $31 and $f31 as source and destination. */
72fcf5ef2aSThomas Huth TCGv zero;
73fcf5ef2aSThomas Huth TCGv sink;
74fcf5ef2aSThomas Huth };
75fcf5ef2aSThomas Huth
76fed14246SRichard Henderson #ifdef CONFIG_USER_ONLY
77fed14246SRichard Henderson #define UNALIGN(C) (C)->unalign
78fed14246SRichard Henderson #else
796ffaac9cSRichard Henderson #define UNALIGN(C) MO_ALIGN
80fed14246SRichard Henderson #endif
81fed14246SRichard Henderson
823de811c6SRichard Henderson /* Target-specific return values from translate_one, indicating the
833de811c6SRichard Henderson state of the TB. Note that DISAS_NEXT indicates that we are not
84fcf5ef2aSThomas Huth exiting the TB. */
853de811c6SRichard Henderson #define DISAS_PC_UPDATED_NOCHAIN DISAS_TARGET_0
863de811c6SRichard Henderson #define DISAS_PC_UPDATED DISAS_TARGET_1
873de811c6SRichard Henderson #define DISAS_PC_STALE DISAS_TARGET_2
88fcf5ef2aSThomas Huth
89fcf5ef2aSThomas Huth /* global register indexes */
90fcf5ef2aSThomas Huth static TCGv cpu_std_ir[31];
91fcf5ef2aSThomas Huth static TCGv cpu_fir[31];
92fcf5ef2aSThomas Huth static TCGv cpu_pc;
93fcf5ef2aSThomas Huth static TCGv cpu_lock_addr;
94fcf5ef2aSThomas Huth static TCGv cpu_lock_value;
95fcf5ef2aSThomas Huth
96fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
97fcf5ef2aSThomas Huth static TCGv cpu_pal_ir[31];
98fcf5ef2aSThomas Huth #endif
99fcf5ef2aSThomas Huth
alpha_translate_init(void)100fcf5ef2aSThomas Huth void alpha_translate_init(void)
101fcf5ef2aSThomas Huth {
102fcf5ef2aSThomas Huth #define DEF_VAR(V) { &cpu_##V, #V, offsetof(CPUAlphaState, V) }
103fcf5ef2aSThomas Huth
104fcf5ef2aSThomas Huth typedef struct { TCGv *var; const char *name; int ofs; } GlobalVar;
105fcf5ef2aSThomas Huth static const GlobalVar vars[] = {
106fcf5ef2aSThomas Huth DEF_VAR(pc),
107fcf5ef2aSThomas Huth DEF_VAR(lock_addr),
108fcf5ef2aSThomas Huth DEF_VAR(lock_value),
109fcf5ef2aSThomas Huth };
110fcf5ef2aSThomas Huth
111fcf5ef2aSThomas Huth #undef DEF_VAR
112fcf5ef2aSThomas Huth
113fcf5ef2aSThomas Huth /* Use the symbolic register names that match the disassembler. */
114fcf5ef2aSThomas Huth static const char greg_names[31][4] = {
115fcf5ef2aSThomas Huth "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
116fcf5ef2aSThomas Huth "t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp",
117fcf5ef2aSThomas Huth "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
118fcf5ef2aSThomas Huth "t10", "t11", "ra", "t12", "at", "gp", "sp"
119fcf5ef2aSThomas Huth };
120fcf5ef2aSThomas Huth static const char freg_names[31][4] = {
121fcf5ef2aSThomas Huth "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
122fcf5ef2aSThomas Huth "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
123fcf5ef2aSThomas Huth "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
124fcf5ef2aSThomas Huth "f24", "f25", "f26", "f27", "f28", "f29", "f30"
125fcf5ef2aSThomas Huth };
126fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
127fcf5ef2aSThomas Huth static const char shadow_names[8][8] = {
128fcf5ef2aSThomas Huth "pal_t7", "pal_s0", "pal_s1", "pal_s2",
129fcf5ef2aSThomas Huth "pal_s3", "pal_s4", "pal_s5", "pal_t11"
130fcf5ef2aSThomas Huth };
131fcf5ef2aSThomas Huth #endif
132fcf5ef2aSThomas Huth
133fcf5ef2aSThomas Huth int i;
134fcf5ef2aSThomas Huth
135fcf5ef2aSThomas Huth for (i = 0; i < 31; i++) {
136ad75a51eSRichard Henderson cpu_std_ir[i] = tcg_global_mem_new_i64(tcg_env,
137fcf5ef2aSThomas Huth offsetof(CPUAlphaState, ir[i]),
138fcf5ef2aSThomas Huth greg_names[i]);
139fcf5ef2aSThomas Huth }
140fcf5ef2aSThomas Huth
141fcf5ef2aSThomas Huth for (i = 0; i < 31; i++) {
142ad75a51eSRichard Henderson cpu_fir[i] = tcg_global_mem_new_i64(tcg_env,
143fcf5ef2aSThomas Huth offsetof(CPUAlphaState, fir[i]),
144fcf5ef2aSThomas Huth freg_names[i]);
145fcf5ef2aSThomas Huth }
146fcf5ef2aSThomas Huth
147fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
148fcf5ef2aSThomas Huth memcpy(cpu_pal_ir, cpu_std_ir, sizeof(cpu_pal_ir));
149fcf5ef2aSThomas Huth for (i = 0; i < 8; i++) {
150fcf5ef2aSThomas Huth int r = (i == 7 ? 25 : i + 8);
151ad75a51eSRichard Henderson cpu_pal_ir[r] = tcg_global_mem_new_i64(tcg_env,
152fcf5ef2aSThomas Huth offsetof(CPUAlphaState,
153fcf5ef2aSThomas Huth shadow[i]),
154fcf5ef2aSThomas Huth shadow_names[i]);
155fcf5ef2aSThomas Huth }
156fcf5ef2aSThomas Huth #endif
157fcf5ef2aSThomas Huth
158fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(vars); ++i) {
159fcf5ef2aSThomas Huth const GlobalVar *v = &vars[i];
160ad75a51eSRichard Henderson *v->var = tcg_global_mem_new_i64(tcg_env, v->ofs, v->name);
161fcf5ef2aSThomas Huth }
162fcf5ef2aSThomas Huth }
163fcf5ef2aSThomas Huth
load_zero(DisasContext * ctx)164fcf5ef2aSThomas Huth static TCGv load_zero(DisasContext *ctx)
165fcf5ef2aSThomas Huth {
166f764718dSRichard Henderson if (!ctx->zero) {
167212c88c0SRichard Henderson ctx->zero = tcg_constant_i64(0);
168fcf5ef2aSThomas Huth }
169fcf5ef2aSThomas Huth return ctx->zero;
170fcf5ef2aSThomas Huth }
171fcf5ef2aSThomas Huth
dest_sink(DisasContext * ctx)172fcf5ef2aSThomas Huth static TCGv dest_sink(DisasContext *ctx)
173fcf5ef2aSThomas Huth {
174f764718dSRichard Henderson if (!ctx->sink) {
175fcf5ef2aSThomas Huth ctx->sink = tcg_temp_new();
176fcf5ef2aSThomas Huth }
177fcf5ef2aSThomas Huth return ctx->sink;
178fcf5ef2aSThomas Huth }
179fcf5ef2aSThomas Huth
free_context_temps(DisasContext * ctx)180fcf5ef2aSThomas Huth static void free_context_temps(DisasContext *ctx)
181fcf5ef2aSThomas Huth {
182f764718dSRichard Henderson if (ctx->sink) {
183fcf5ef2aSThomas Huth tcg_gen_discard_i64(ctx->sink);
184f764718dSRichard Henderson ctx->sink = NULL;
185fcf5ef2aSThomas Huth }
186fcf5ef2aSThomas Huth }
187fcf5ef2aSThomas Huth
load_gpr(DisasContext * ctx,unsigned reg)188fcf5ef2aSThomas Huth static TCGv load_gpr(DisasContext *ctx, unsigned reg)
189fcf5ef2aSThomas Huth {
190fcf5ef2aSThomas Huth if (likely(reg < 31)) {
191fcf5ef2aSThomas Huth return ctx->ir[reg];
192fcf5ef2aSThomas Huth } else {
193fcf5ef2aSThomas Huth return load_zero(ctx);
194fcf5ef2aSThomas Huth }
195fcf5ef2aSThomas Huth }
196fcf5ef2aSThomas Huth
load_gpr_lit(DisasContext * ctx,unsigned reg,uint8_t lit,bool islit)197fcf5ef2aSThomas Huth static TCGv load_gpr_lit(DisasContext *ctx, unsigned reg,
198fcf5ef2aSThomas Huth uint8_t lit, bool islit)
199fcf5ef2aSThomas Huth {
200fcf5ef2aSThomas Huth if (islit) {
201212c88c0SRichard Henderson return tcg_constant_i64(lit);
202fcf5ef2aSThomas Huth } else if (likely(reg < 31)) {
203fcf5ef2aSThomas Huth return ctx->ir[reg];
204fcf5ef2aSThomas Huth } else {
205fcf5ef2aSThomas Huth return load_zero(ctx);
206fcf5ef2aSThomas Huth }
207fcf5ef2aSThomas Huth }
208fcf5ef2aSThomas Huth
dest_gpr(DisasContext * ctx,unsigned reg)209fcf5ef2aSThomas Huth static TCGv dest_gpr(DisasContext *ctx, unsigned reg)
210fcf5ef2aSThomas Huth {
211fcf5ef2aSThomas Huth if (likely(reg < 31)) {
212fcf5ef2aSThomas Huth return ctx->ir[reg];
213fcf5ef2aSThomas Huth } else {
214fcf5ef2aSThomas Huth return dest_sink(ctx);
215fcf5ef2aSThomas Huth }
216fcf5ef2aSThomas Huth }
217fcf5ef2aSThomas Huth
load_fpr(DisasContext * ctx,unsigned reg)218fcf5ef2aSThomas Huth static TCGv load_fpr(DisasContext *ctx, unsigned reg)
219fcf5ef2aSThomas Huth {
220fcf5ef2aSThomas Huth if (likely(reg < 31)) {
221fcf5ef2aSThomas Huth return cpu_fir[reg];
222fcf5ef2aSThomas Huth } else {
223fcf5ef2aSThomas Huth return load_zero(ctx);
224fcf5ef2aSThomas Huth }
225fcf5ef2aSThomas Huth }
226fcf5ef2aSThomas Huth
dest_fpr(DisasContext * ctx,unsigned reg)227fcf5ef2aSThomas Huth static TCGv dest_fpr(DisasContext *ctx, unsigned reg)
228fcf5ef2aSThomas Huth {
229fcf5ef2aSThomas Huth if (likely(reg < 31)) {
230fcf5ef2aSThomas Huth return cpu_fir[reg];
231fcf5ef2aSThomas Huth } else {
232fcf5ef2aSThomas Huth return dest_sink(ctx);
233fcf5ef2aSThomas Huth }
234fcf5ef2aSThomas Huth }
235fcf5ef2aSThomas Huth
get_flag_ofs(unsigned shift)236bcd2625dSRichard Henderson static int get_flag_ofs(unsigned shift)
237bcd2625dSRichard Henderson {
238bcd2625dSRichard Henderson int ofs = offsetof(CPUAlphaState, flags);
239e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
240bcd2625dSRichard Henderson ofs += 3 - (shift / 8);
241bcd2625dSRichard Henderson #else
242bcd2625dSRichard Henderson ofs += shift / 8;
243bcd2625dSRichard Henderson #endif
244bcd2625dSRichard Henderson return ofs;
245bcd2625dSRichard Henderson }
246bcd2625dSRichard Henderson
ld_flag_byte(TCGv val,unsigned shift)247bcd2625dSRichard Henderson static void ld_flag_byte(TCGv val, unsigned shift)
248bcd2625dSRichard Henderson {
249ad75a51eSRichard Henderson tcg_gen_ld8u_i64(val, tcg_env, get_flag_ofs(shift));
250bcd2625dSRichard Henderson }
251bcd2625dSRichard Henderson
st_flag_byte(TCGv val,unsigned shift)252bcd2625dSRichard Henderson static void st_flag_byte(TCGv val, unsigned shift)
253bcd2625dSRichard Henderson {
254ad75a51eSRichard Henderson tcg_gen_st8_i64(val, tcg_env, get_flag_ofs(shift));
255bcd2625dSRichard Henderson }
256bcd2625dSRichard Henderson
gen_pc_disp(DisasContext * ctx,TCGv dest,int32_t disp)257b1a3eacfSRichard Henderson static void gen_pc_disp(DisasContext *ctx, TCGv dest, int32_t disp)
258b1a3eacfSRichard Henderson {
259*23bb0863SRichard Henderson uint64_t addr = ctx->base.pc_next + disp;
260*23bb0863SRichard Henderson if (ctx->pcrel) {
261*23bb0863SRichard Henderson tcg_gen_addi_i64(dest, cpu_pc, addr - ctx->base.pc_first);
262*23bb0863SRichard Henderson } else {
263*23bb0863SRichard Henderson tcg_gen_movi_i64(dest, addr);
264*23bb0863SRichard Henderson }
265b1a3eacfSRichard Henderson }
266b1a3eacfSRichard Henderson
gen_excp_1(int exception,int error_code)267fcf5ef2aSThomas Huth static void gen_excp_1(int exception, int error_code)
268fcf5ef2aSThomas Huth {
269fcf5ef2aSThomas Huth TCGv_i32 tmp1, tmp2;
270fcf5ef2aSThomas Huth
271904bd855SRichard Henderson tmp1 = tcg_constant_i32(exception);
272904bd855SRichard Henderson tmp2 = tcg_constant_i32(error_code);
273ad75a51eSRichard Henderson gen_helper_excp(tcg_env, tmp1, tmp2);
274fcf5ef2aSThomas Huth }
275fcf5ef2aSThomas Huth
gen_excp(DisasContext * ctx,int exception,int error_code)2763de811c6SRichard Henderson static DisasJumpType gen_excp(DisasContext *ctx, int exception, int error_code)
277fcf5ef2aSThomas Huth {
278b1a3eacfSRichard Henderson gen_pc_disp(ctx, cpu_pc, 0);
279fcf5ef2aSThomas Huth gen_excp_1(exception, error_code);
2803de811c6SRichard Henderson return DISAS_NORETURN;
281fcf5ef2aSThomas Huth }
282fcf5ef2aSThomas Huth
gen_invalid(DisasContext * ctx)2833de811c6SRichard Henderson static inline DisasJumpType gen_invalid(DisasContext *ctx)
284fcf5ef2aSThomas Huth {
285fcf5ef2aSThomas Huth return gen_excp(ctx, EXCP_OPCDEC, 0);
286fcf5ef2aSThomas Huth }
287fcf5ef2aSThomas Huth
gen_ldf(DisasContext * ctx,TCGv dest,TCGv addr)28845263531SRichard Henderson static void gen_ldf(DisasContext *ctx, TCGv dest, TCGv addr)
289fcf5ef2aSThomas Huth {
290fcf5ef2aSThomas Huth TCGv_i32 tmp32 = tcg_temp_new_i32();
291fed14246SRichard Henderson tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
29245263531SRichard Henderson gen_helper_memory_to_f(dest, tmp32);
293fcf5ef2aSThomas Huth }
294fcf5ef2aSThomas Huth
gen_ldg(DisasContext * ctx,TCGv dest,TCGv addr)29545263531SRichard Henderson static void gen_ldg(DisasContext *ctx, TCGv dest, TCGv addr)
296fcf5ef2aSThomas Huth {
297fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new();
298fc313c64SFrédéric Pétrot tcg_gen_qemu_ld_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
29945263531SRichard Henderson gen_helper_memory_to_g(dest, tmp);
300fcf5ef2aSThomas Huth }
301fcf5ef2aSThomas Huth
gen_lds(DisasContext * ctx,TCGv dest,TCGv addr)30245263531SRichard Henderson static void gen_lds(DisasContext *ctx, TCGv dest, TCGv addr)
303fcf5ef2aSThomas Huth {
304fcf5ef2aSThomas Huth TCGv_i32 tmp32 = tcg_temp_new_i32();
305fed14246SRichard Henderson tcg_gen_qemu_ld_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
30645263531SRichard Henderson gen_helper_memory_to_s(dest, tmp32);
307fcf5ef2aSThomas Huth }
308fcf5ef2aSThomas Huth
gen_ldt(DisasContext * ctx,TCGv dest,TCGv addr)30945263531SRichard Henderson static void gen_ldt(DisasContext *ctx, TCGv dest, TCGv addr)
31045263531SRichard Henderson {
311fc313c64SFrédéric Pétrot tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
31245263531SRichard Henderson }
31345263531SRichard Henderson
gen_load_fp(DisasContext * ctx,int ra,int rb,int32_t disp16,void (* func)(DisasContext *,TCGv,TCGv))31445263531SRichard Henderson static void gen_load_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
31545263531SRichard Henderson void (*func)(DisasContext *, TCGv, TCGv))
31645263531SRichard Henderson {
31745263531SRichard Henderson /* Loads to $f31 are prefetches, which we can treat as nops. */
31845263531SRichard Henderson if (likely(ra != 31)) {
31945263531SRichard Henderson TCGv addr = tcg_temp_new();
32045263531SRichard Henderson tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
32145263531SRichard Henderson func(ctx, cpu_fir[ra], addr);
32245263531SRichard Henderson }
32345263531SRichard Henderson }
32445263531SRichard Henderson
gen_load_int(DisasContext * ctx,int ra,int rb,int32_t disp16,MemOp op,bool clear,bool locked)3255ffcb334SRichard Henderson static void gen_load_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
3265ffcb334SRichard Henderson MemOp op, bool clear, bool locked)
327fcf5ef2aSThomas Huth {
3285ffcb334SRichard Henderson TCGv addr, dest;
329fcf5ef2aSThomas Huth
330fcf5ef2aSThomas Huth /* LDQ_U with ra $31 is UNOP. Other various loads are forms of
331fcf5ef2aSThomas Huth prefetches, which we can treat as nops. No worries about
332fcf5ef2aSThomas Huth missed exceptions here. */
333fcf5ef2aSThomas Huth if (unlikely(ra == 31)) {
334fcf5ef2aSThomas Huth return;
335fcf5ef2aSThomas Huth }
336fcf5ef2aSThomas Huth
3375ffcb334SRichard Henderson addr = tcg_temp_new();
3385ffcb334SRichard Henderson tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
339fcf5ef2aSThomas Huth if (clear) {
3405ffcb334SRichard Henderson tcg_gen_andi_i64(addr, addr, ~0x7);
341fed14246SRichard Henderson } else if (!locked) {
342fed14246SRichard Henderson op |= UNALIGN(ctx);
343fcf5ef2aSThomas Huth }
344fcf5ef2aSThomas Huth
3455ffcb334SRichard Henderson dest = ctx->ir[ra];
3465ffcb334SRichard Henderson tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, op);
347fcf5ef2aSThomas Huth
3485ffcb334SRichard Henderson if (locked) {
3495ffcb334SRichard Henderson tcg_gen_mov_i64(cpu_lock_addr, addr);
3505ffcb334SRichard Henderson tcg_gen_mov_i64(cpu_lock_value, dest);
3515ffcb334SRichard Henderson }
352fcf5ef2aSThomas Huth }
353fcf5ef2aSThomas Huth
gen_stf(DisasContext * ctx,TCGv src,TCGv addr)35445263531SRichard Henderson static void gen_stf(DisasContext *ctx, TCGv src, TCGv addr)
355fcf5ef2aSThomas Huth {
356fcf5ef2aSThomas Huth TCGv_i32 tmp32 = tcg_temp_new_i32();
35745263531SRichard Henderson gen_helper_f_to_memory(tmp32, addr);
358fed14246SRichard Henderson tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
359fcf5ef2aSThomas Huth }
360fcf5ef2aSThomas Huth
gen_stg(DisasContext * ctx,TCGv src,TCGv addr)36145263531SRichard Henderson static void gen_stg(DisasContext *ctx, TCGv src, TCGv addr)
362fcf5ef2aSThomas Huth {
363fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new();
36445263531SRichard Henderson gen_helper_g_to_memory(tmp, src);
365fc313c64SFrédéric Pétrot tcg_gen_qemu_st_i64(tmp, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
366fcf5ef2aSThomas Huth }
367fcf5ef2aSThomas Huth
gen_sts(DisasContext * ctx,TCGv src,TCGv addr)36845263531SRichard Henderson static void gen_sts(DisasContext *ctx, TCGv src, TCGv addr)
369fcf5ef2aSThomas Huth {
370fcf5ef2aSThomas Huth TCGv_i32 tmp32 = tcg_temp_new_i32();
37145263531SRichard Henderson gen_helper_s_to_memory(tmp32, src);
372fed14246SRichard Henderson tcg_gen_qemu_st_i32(tmp32, addr, ctx->mem_idx, MO_LEUL | UNALIGN(ctx));
373fcf5ef2aSThomas Huth }
374fcf5ef2aSThomas Huth
gen_stt(DisasContext * ctx,TCGv src,TCGv addr)37545263531SRichard Henderson static void gen_stt(DisasContext *ctx, TCGv src, TCGv addr)
37645263531SRichard Henderson {
377fc313c64SFrédéric Pétrot tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, MO_LEUQ | UNALIGN(ctx));
37845263531SRichard Henderson }
37945263531SRichard Henderson
gen_store_fp(DisasContext * ctx,int ra,int rb,int32_t disp16,void (* func)(DisasContext *,TCGv,TCGv))38045263531SRichard Henderson static void gen_store_fp(DisasContext *ctx, int ra, int rb, int32_t disp16,
38145263531SRichard Henderson void (*func)(DisasContext *, TCGv, TCGv))
38245263531SRichard Henderson {
38345263531SRichard Henderson TCGv addr = tcg_temp_new();
38445263531SRichard Henderson tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
38545263531SRichard Henderson func(ctx, load_fpr(ctx, ra), addr);
38645263531SRichard Henderson }
38745263531SRichard Henderson
gen_store_int(DisasContext * ctx,int ra,int rb,int32_t disp16,MemOp op,bool clear)3885ffcb334SRichard Henderson static void gen_store_int(DisasContext *ctx, int ra, int rb, int32_t disp16,
3895ffcb334SRichard Henderson MemOp op, bool clear)
390fcf5ef2aSThomas Huth {
3915ffcb334SRichard Henderson TCGv addr, src;
392fcf5ef2aSThomas Huth
3935ffcb334SRichard Henderson addr = tcg_temp_new();
3945ffcb334SRichard Henderson tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
395fcf5ef2aSThomas Huth if (clear) {
3965ffcb334SRichard Henderson tcg_gen_andi_i64(addr, addr, ~0x7);
397fed14246SRichard Henderson } else {
398fed14246SRichard Henderson op |= UNALIGN(ctx);
399fcf5ef2aSThomas Huth }
400fcf5ef2aSThomas Huth
4015ffcb334SRichard Henderson src = load_gpr(ctx, ra);
4025ffcb334SRichard Henderson tcg_gen_qemu_st_i64(src, addr, ctx->mem_idx, op);
403fcf5ef2aSThomas Huth }
404fcf5ef2aSThomas Huth
gen_store_conditional(DisasContext * ctx,int ra,int rb,int32_t disp16,int mem_idx,MemOp op)4053de811c6SRichard Henderson static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
406fcf5ef2aSThomas Huth int32_t disp16, int mem_idx,
40714776ab5STony Nguyen MemOp op)
408fcf5ef2aSThomas Huth {
409fcf5ef2aSThomas Huth TCGLabel *lab_fail, *lab_done;
410fcf5ef2aSThomas Huth TCGv addr, val;
411fcf5ef2aSThomas Huth
412fcf5ef2aSThomas Huth addr = tcg_temp_new_i64();
413fcf5ef2aSThomas Huth tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16);
414fcf5ef2aSThomas Huth free_context_temps(ctx);
415fcf5ef2aSThomas Huth
416fcf5ef2aSThomas Huth lab_fail = gen_new_label();
417fcf5ef2aSThomas Huth lab_done = gen_new_label();
418fcf5ef2aSThomas Huth tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
419fcf5ef2aSThomas Huth
420fcf5ef2aSThomas Huth val = tcg_temp_new_i64();
421fcf5ef2aSThomas Huth tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value,
422fcf5ef2aSThomas Huth load_gpr(ctx, ra), mem_idx, op);
423fcf5ef2aSThomas Huth free_context_temps(ctx);
424fcf5ef2aSThomas Huth
425fcf5ef2aSThomas Huth if (ra != 31) {
426fcf5ef2aSThomas Huth tcg_gen_setcond_i64(TCG_COND_EQ, ctx->ir[ra], val, cpu_lock_value);
427fcf5ef2aSThomas Huth }
428fcf5ef2aSThomas Huth tcg_gen_br(lab_done);
429fcf5ef2aSThomas Huth
430fcf5ef2aSThomas Huth gen_set_label(lab_fail);
431fcf5ef2aSThomas Huth if (ra != 31) {
432fcf5ef2aSThomas Huth tcg_gen_movi_i64(ctx->ir[ra], 0);
433fcf5ef2aSThomas Huth }
434fcf5ef2aSThomas Huth
435fcf5ef2aSThomas Huth gen_set_label(lab_done);
436fcf5ef2aSThomas Huth tcg_gen_movi_i64(cpu_lock_addr, -1);
4373de811c6SRichard Henderson return DISAS_NEXT;
438fcf5ef2aSThomas Huth }
439fcf5ef2aSThomas Huth
gen_goto_tb(DisasContext * ctx,int idx,int32_t disp)44082b60d25SRichard Henderson static void gen_goto_tb(DisasContext *ctx, int idx, int32_t disp)
441fcf5ef2aSThomas Huth {
442b1a3eacfSRichard Henderson if (translator_use_goto_tb(&ctx->base, ctx->base.pc_next + disp)) {
443*23bb0863SRichard Henderson /* With PCREL, PC must always be up-to-date. */
444*23bb0863SRichard Henderson if (ctx->pcrel) {
445*23bb0863SRichard Henderson gen_pc_disp(ctx, cpu_pc, disp);
446*23bb0863SRichard Henderson tcg_gen_goto_tb(idx);
447*23bb0863SRichard Henderson } else {
44882b60d25SRichard Henderson tcg_gen_goto_tb(idx);
449b1a3eacfSRichard Henderson gen_pc_disp(ctx, cpu_pc, disp);
450*23bb0863SRichard Henderson }
45182b60d25SRichard Henderson tcg_gen_exit_tb(ctx->base.tb, idx);
45282b60d25SRichard Henderson } else {
453b1a3eacfSRichard Henderson gen_pc_disp(ctx, cpu_pc, disp);
45482b60d25SRichard Henderson tcg_gen_lookup_and_goto_ptr();
45582b60d25SRichard Henderson }
456fcf5ef2aSThomas Huth }
457fcf5ef2aSThomas Huth
gen_bdirect(DisasContext * ctx,int ra,int32_t disp)4583de811c6SRichard Henderson static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
459fcf5ef2aSThomas Huth {
460fcf5ef2aSThomas Huth if (ra != 31) {
461b1a3eacfSRichard Henderson gen_pc_disp(ctx, ctx->ir[ra], 0);
462fcf5ef2aSThomas Huth }
463fcf5ef2aSThomas Huth
464fcf5ef2aSThomas Huth /* Notice branch-to-next; used to initialize RA with the PC. */
465fcf5ef2aSThomas Huth if (disp == 0) {
4660cda93c9SRichard Henderson return DISAS_NEXT;
4670cda93c9SRichard Henderson }
46882b60d25SRichard Henderson gen_goto_tb(ctx, 0, disp);
4699804ab26SRichard Henderson return DISAS_NORETURN;
470fcf5ef2aSThomas Huth }
471fcf5ef2aSThomas Huth
gen_bcond_internal(DisasContext * ctx,TCGCond cond,TCGv cmp,uint64_t imm,int32_t disp)4723de811c6SRichard Henderson static DisasJumpType gen_bcond_internal(DisasContext *ctx, TCGCond cond,
47342c47f63SRichard Henderson TCGv cmp, uint64_t imm, int32_t disp)
474fcf5ef2aSThomas Huth {
475fcf5ef2aSThomas Huth TCGLabel *lab_true = gen_new_label();
476fcf5ef2aSThomas Huth
47742c47f63SRichard Henderson tcg_gen_brcondi_i64(cond, cmp, imm, lab_true);
47882b60d25SRichard Henderson gen_goto_tb(ctx, 0, 0);
479fcf5ef2aSThomas Huth gen_set_label(lab_true);
48082b60d25SRichard Henderson gen_goto_tb(ctx, 1, disp);
4819804ab26SRichard Henderson
4829804ab26SRichard Henderson return DISAS_NORETURN;
483fcf5ef2aSThomas Huth }
484fcf5ef2aSThomas Huth
gen_bcond(DisasContext * ctx,TCGCond cond,int ra,int32_t disp)4853de811c6SRichard Henderson static DisasJumpType gen_bcond(DisasContext *ctx, TCGCond cond, int ra,
486c66ba978SRichard Henderson int32_t disp)
487fcf5ef2aSThomas Huth {
48842c47f63SRichard Henderson return gen_bcond_internal(ctx, cond, load_gpr(ctx, ra),
489c66ba978SRichard Henderson is_tst_cond(cond), disp);
490fcf5ef2aSThomas Huth }
491fcf5ef2aSThomas Huth
492fcf5ef2aSThomas Huth /* Fold -0.0 for comparison with COND. */
493fcf5ef2aSThomas Huth
gen_fold_mzero(TCGCond * pcond,uint64_t * pimm,TCGv_i64 src)494630ee069SRichard Henderson static TCGv_i64 gen_fold_mzero(TCGCond *pcond, uint64_t *pimm, TCGv_i64 src)
495fcf5ef2aSThomas Huth {
496630ee069SRichard Henderson TCGv_i64 tmp;
497fcf5ef2aSThomas Huth
498630ee069SRichard Henderson *pimm = 0;
499630ee069SRichard Henderson switch (*pcond) {
500fcf5ef2aSThomas Huth case TCG_COND_LE:
501fcf5ef2aSThomas Huth case TCG_COND_GT:
502fcf5ef2aSThomas Huth /* For <= or >, the -0.0 value directly compares the way we want. */
503630ee069SRichard Henderson return src;
504fcf5ef2aSThomas Huth
505fcf5ef2aSThomas Huth case TCG_COND_EQ:
506fcf5ef2aSThomas Huth case TCG_COND_NE:
507630ee069SRichard Henderson /* For == or !=, we can compare without the sign bit. */
508630ee069SRichard Henderson *pcond = *pcond == TCG_COND_EQ ? TCG_COND_TSTEQ : TCG_COND_TSTNE;
509630ee069SRichard Henderson *pimm = INT64_MAX;
510630ee069SRichard Henderson return src;
511fcf5ef2aSThomas Huth
512fcf5ef2aSThomas Huth case TCG_COND_GE:
513fcf5ef2aSThomas Huth case TCG_COND_LT:
514d55a3211SRichard Henderson /* For >= or <, map -0.0 to +0.0. */
515630ee069SRichard Henderson tmp = tcg_temp_new_i64();
516630ee069SRichard Henderson tcg_gen_movcond_i64(TCG_COND_EQ, tmp,
517630ee069SRichard Henderson src, tcg_constant_i64(INT64_MIN),
518630ee069SRichard Henderson tcg_constant_i64(0), src);
519630ee069SRichard Henderson return tmp;
520fcf5ef2aSThomas Huth
521fcf5ef2aSThomas Huth default:
522630ee069SRichard Henderson g_assert_not_reached();
523fcf5ef2aSThomas Huth }
524fcf5ef2aSThomas Huth }
525fcf5ef2aSThomas Huth
gen_fbcond(DisasContext * ctx,TCGCond cond,int ra,int32_t disp)5263de811c6SRichard Henderson static DisasJumpType gen_fbcond(DisasContext *ctx, TCGCond cond, int ra,
527fcf5ef2aSThomas Huth int32_t disp)
528fcf5ef2aSThomas Huth {
529630ee069SRichard Henderson uint64_t imm;
530630ee069SRichard Henderson TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra));
531630ee069SRichard Henderson return gen_bcond_internal(ctx, cond, tmp, imm, disp);
532fcf5ef2aSThomas Huth }
533fcf5ef2aSThomas Huth
gen_fcmov(DisasContext * ctx,TCGCond cond,int ra,int rb,int rc)534fcf5ef2aSThomas Huth static void gen_fcmov(DisasContext *ctx, TCGCond cond, int ra, int rb, int rc)
535fcf5ef2aSThomas Huth {
536630ee069SRichard Henderson uint64_t imm;
537630ee069SRichard Henderson TCGv_i64 tmp = gen_fold_mzero(&cond, &imm, load_fpr(ctx, ra));
538630ee069SRichard Henderson tcg_gen_movcond_i64(cond, dest_fpr(ctx, rc),
539630ee069SRichard Henderson tmp, tcg_constant_i64(imm),
540630ee069SRichard Henderson load_fpr(ctx, rb), load_fpr(ctx, rc));
541fcf5ef2aSThomas Huth }
542fcf5ef2aSThomas Huth
543fcf5ef2aSThomas Huth #define QUAL_RM_N 0x080 /* Round mode nearest even */
544fcf5ef2aSThomas Huth #define QUAL_RM_C 0x000 /* Round mode chopped */
545fcf5ef2aSThomas Huth #define QUAL_RM_M 0x040 /* Round mode minus infinity */
546fcf5ef2aSThomas Huth #define QUAL_RM_D 0x0c0 /* Round mode dynamic */
547fcf5ef2aSThomas Huth #define QUAL_RM_MASK 0x0c0
548fcf5ef2aSThomas Huth
549fcf5ef2aSThomas Huth #define QUAL_U 0x100 /* Underflow enable (fp output) */
550fcf5ef2aSThomas Huth #define QUAL_V 0x100 /* Overflow enable (int output) */
551fcf5ef2aSThomas Huth #define QUAL_S 0x400 /* Software completion enable */
552fcf5ef2aSThomas Huth #define QUAL_I 0x200 /* Inexact detection enable */
553fcf5ef2aSThomas Huth
gen_qual_roundmode(DisasContext * ctx,int fn11)554fcf5ef2aSThomas Huth static void gen_qual_roundmode(DisasContext *ctx, int fn11)
555fcf5ef2aSThomas Huth {
556fcf5ef2aSThomas Huth TCGv_i32 tmp;
557fcf5ef2aSThomas Huth
558fcf5ef2aSThomas Huth fn11 &= QUAL_RM_MASK;
559fcf5ef2aSThomas Huth if (fn11 == ctx->tb_rm) {
560fcf5ef2aSThomas Huth return;
561fcf5ef2aSThomas Huth }
562fcf5ef2aSThomas Huth ctx->tb_rm = fn11;
563fcf5ef2aSThomas Huth
564fcf5ef2aSThomas Huth tmp = tcg_temp_new_i32();
565fcf5ef2aSThomas Huth switch (fn11) {
566fcf5ef2aSThomas Huth case QUAL_RM_N:
567fcf5ef2aSThomas Huth tcg_gen_movi_i32(tmp, float_round_nearest_even);
568fcf5ef2aSThomas Huth break;
569fcf5ef2aSThomas Huth case QUAL_RM_C:
570fcf5ef2aSThomas Huth tcg_gen_movi_i32(tmp, float_round_to_zero);
571fcf5ef2aSThomas Huth break;
572fcf5ef2aSThomas Huth case QUAL_RM_M:
573fcf5ef2aSThomas Huth tcg_gen_movi_i32(tmp, float_round_down);
574fcf5ef2aSThomas Huth break;
575fcf5ef2aSThomas Huth case QUAL_RM_D:
576ad75a51eSRichard Henderson tcg_gen_ld8u_i32(tmp, tcg_env,
577fcf5ef2aSThomas Huth offsetof(CPUAlphaState, fpcr_dyn_round));
578fcf5ef2aSThomas Huth break;
579fcf5ef2aSThomas Huth }
580fcf5ef2aSThomas Huth
581fcf5ef2aSThomas Huth #if defined(CONFIG_SOFTFLOAT_INLINE)
582fcf5ef2aSThomas Huth /* ??? The "fpu/softfloat.h" interface is to call set_float_rounding_mode.
583fcf5ef2aSThomas Huth With CONFIG_SOFTFLOAT that expands to an out-of-line call that just
584fcf5ef2aSThomas Huth sets the one field. */
585ad75a51eSRichard Henderson tcg_gen_st8_i32(tmp, tcg_env,
586fcf5ef2aSThomas Huth offsetof(CPUAlphaState, fp_status.float_rounding_mode));
587fcf5ef2aSThomas Huth #else
588fcf5ef2aSThomas Huth gen_helper_setroundmode(tmp);
589fcf5ef2aSThomas Huth #endif
590fcf5ef2aSThomas Huth }
591fcf5ef2aSThomas Huth
gen_qual_flushzero(DisasContext * ctx,int fn11)592fcf5ef2aSThomas Huth static void gen_qual_flushzero(DisasContext *ctx, int fn11)
593fcf5ef2aSThomas Huth {
594fcf5ef2aSThomas Huth TCGv_i32 tmp;
595fcf5ef2aSThomas Huth
596fcf5ef2aSThomas Huth fn11 &= QUAL_U;
597fcf5ef2aSThomas Huth if (fn11 == ctx->tb_ftz) {
598fcf5ef2aSThomas Huth return;
599fcf5ef2aSThomas Huth }
600fcf5ef2aSThomas Huth ctx->tb_ftz = fn11;
601fcf5ef2aSThomas Huth
602fcf5ef2aSThomas Huth tmp = tcg_temp_new_i32();
603fcf5ef2aSThomas Huth if (fn11) {
604fcf5ef2aSThomas Huth /* Underflow is enabled, use the FPCR setting. */
605ad75a51eSRichard Henderson tcg_gen_ld8u_i32(tmp, tcg_env,
606fcf5ef2aSThomas Huth offsetof(CPUAlphaState, fpcr_flush_to_zero));
607fcf5ef2aSThomas Huth } else {
608fcf5ef2aSThomas Huth /* Underflow is disabled, force flush-to-zero. */
609fcf5ef2aSThomas Huth tcg_gen_movi_i32(tmp, 1);
610fcf5ef2aSThomas Huth }
611fcf5ef2aSThomas Huth
612fcf5ef2aSThomas Huth #if defined(CONFIG_SOFTFLOAT_INLINE)
613ad75a51eSRichard Henderson tcg_gen_st8_i32(tmp, tcg_env,
614fcf5ef2aSThomas Huth offsetof(CPUAlphaState, fp_status.flush_to_zero));
615fcf5ef2aSThomas Huth #else
616fcf5ef2aSThomas Huth gen_helper_setflushzero(tmp);
617fcf5ef2aSThomas Huth #endif
618fcf5ef2aSThomas Huth }
619fcf5ef2aSThomas Huth
gen_ieee_input(DisasContext * ctx,int reg,int fn11,int is_cmp)620fcf5ef2aSThomas Huth static TCGv gen_ieee_input(DisasContext *ctx, int reg, int fn11, int is_cmp)
621fcf5ef2aSThomas Huth {
622fcf5ef2aSThomas Huth TCGv val;
623fcf5ef2aSThomas Huth
624fcf5ef2aSThomas Huth if (unlikely(reg == 31)) {
625fcf5ef2aSThomas Huth val = load_zero(ctx);
626fcf5ef2aSThomas Huth } else {
627fcf5ef2aSThomas Huth val = cpu_fir[reg];
628fcf5ef2aSThomas Huth if ((fn11 & QUAL_S) == 0) {
629fcf5ef2aSThomas Huth if (is_cmp) {
630ad75a51eSRichard Henderson gen_helper_ieee_input_cmp(tcg_env, val);
631fcf5ef2aSThomas Huth } else {
632ad75a51eSRichard Henderson gen_helper_ieee_input(tcg_env, val);
633fcf5ef2aSThomas Huth }
634fcf5ef2aSThomas Huth } else {
635fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
636fcf5ef2aSThomas Huth /* In system mode, raise exceptions for denormals like real
637fcf5ef2aSThomas Huth hardware. In user mode, proceed as if the OS completion
638fcf5ef2aSThomas Huth handler is handling the denormal as per spec. */
639ad75a51eSRichard Henderson gen_helper_ieee_input_s(tcg_env, val);
640fcf5ef2aSThomas Huth #endif
641fcf5ef2aSThomas Huth }
642fcf5ef2aSThomas Huth }
643fcf5ef2aSThomas Huth return val;
644fcf5ef2aSThomas Huth }
645fcf5ef2aSThomas Huth
gen_fp_exc_raise(int rc,int fn11)646fcf5ef2aSThomas Huth static void gen_fp_exc_raise(int rc, int fn11)
647fcf5ef2aSThomas Huth {
648fcf5ef2aSThomas Huth /* ??? We ought to be able to do something with imprecise exceptions.
649fcf5ef2aSThomas Huth E.g. notice we're still in the trap shadow of something within the
650fcf5ef2aSThomas Huth TB and do not generate the code to signal the exception; end the TB
651fcf5ef2aSThomas Huth when an exception is forced to arrive, either by consumption of a
652fcf5ef2aSThomas Huth register value or TRAPB or EXCB. */
653fcf5ef2aSThomas Huth TCGv_i32 reg, ign;
654fcf5ef2aSThomas Huth uint32_t ignore = 0;
655fcf5ef2aSThomas Huth
656fcf5ef2aSThomas Huth if (!(fn11 & QUAL_U)) {
657fcf5ef2aSThomas Huth /* Note that QUAL_U == QUAL_V, so ignore either. */
658fcf5ef2aSThomas Huth ignore |= FPCR_UNF | FPCR_IOV;
659fcf5ef2aSThomas Huth }
660fcf5ef2aSThomas Huth if (!(fn11 & QUAL_I)) {
661fcf5ef2aSThomas Huth ignore |= FPCR_INE;
662fcf5ef2aSThomas Huth }
663904bd855SRichard Henderson ign = tcg_constant_i32(ignore);
664fcf5ef2aSThomas Huth
665fcf5ef2aSThomas Huth /* ??? Pass in the regno of the destination so that the helper can
666fcf5ef2aSThomas Huth set EXC_MASK, which contains a bitmask of destination registers
667fcf5ef2aSThomas Huth that have caused arithmetic traps. A simple userspace emulation
668fcf5ef2aSThomas Huth does not require this. We do need it for a guest kernel's entArith,
669fcf5ef2aSThomas Huth or if we were to do something clever with imprecise exceptions. */
670904bd855SRichard Henderson reg = tcg_constant_i32(rc + 32);
671fcf5ef2aSThomas Huth if (fn11 & QUAL_S) {
672ad75a51eSRichard Henderson gen_helper_fp_exc_raise_s(tcg_env, ign, reg);
673fcf5ef2aSThomas Huth } else {
674ad75a51eSRichard Henderson gen_helper_fp_exc_raise(tcg_env, ign, reg);
675fcf5ef2aSThomas Huth }
676fcf5ef2aSThomas Huth }
677fcf5ef2aSThomas Huth
gen_cvtlq(TCGv vc,TCGv vb)678fcf5ef2aSThomas Huth static void gen_cvtlq(TCGv vc, TCGv vb)
679fcf5ef2aSThomas Huth {
680fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new();
681fcf5ef2aSThomas Huth
682fcf5ef2aSThomas Huth /* The arithmetic right shift here, plus the sign-extended mask below
683fcf5ef2aSThomas Huth yields a sign-extended result without an explicit ext32s_i64. */
684729028a6SPhilippe Mathieu-Daudé tcg_gen_shri_i64(tmp, vb, 29);
685729028a6SPhilippe Mathieu-Daudé tcg_gen_sari_i64(vc, vb, 32);
686729028a6SPhilippe Mathieu-Daudé tcg_gen_deposit_i64(vc, vc, tmp, 0, 30);
687fcf5ef2aSThomas Huth }
688fcf5ef2aSThomas Huth
gen_ieee_arith2(DisasContext * ctx,void (* helper)(TCGv,TCGv_ptr,TCGv),int rb,int rc,int fn11)689fcf5ef2aSThomas Huth static void gen_ieee_arith2(DisasContext *ctx,
690fcf5ef2aSThomas Huth void (*helper)(TCGv, TCGv_ptr, TCGv),
691fcf5ef2aSThomas Huth int rb, int rc, int fn11)
692fcf5ef2aSThomas Huth {
693fcf5ef2aSThomas Huth TCGv vb;
694fcf5ef2aSThomas Huth
695fcf5ef2aSThomas Huth gen_qual_roundmode(ctx, fn11);
696fcf5ef2aSThomas Huth gen_qual_flushzero(ctx, fn11);
697fcf5ef2aSThomas Huth
698fcf5ef2aSThomas Huth vb = gen_ieee_input(ctx, rb, fn11, 0);
699ad75a51eSRichard Henderson helper(dest_fpr(ctx, rc), tcg_env, vb);
700fcf5ef2aSThomas Huth
701fcf5ef2aSThomas Huth gen_fp_exc_raise(rc, fn11);
702fcf5ef2aSThomas Huth }
703fcf5ef2aSThomas Huth
704fcf5ef2aSThomas Huth #define IEEE_ARITH2(name) \
705fcf5ef2aSThomas Huth static inline void glue(gen_, name)(DisasContext *ctx, \
706fcf5ef2aSThomas Huth int rb, int rc, int fn11) \
707fcf5ef2aSThomas Huth { \
708fcf5ef2aSThomas Huth gen_ieee_arith2(ctx, gen_helper_##name, rb, rc, fn11); \
709fcf5ef2aSThomas Huth }
710fcf5ef2aSThomas Huth IEEE_ARITH2(sqrts)
IEEE_ARITH2(sqrtt)711fcf5ef2aSThomas Huth IEEE_ARITH2(sqrtt)
712fcf5ef2aSThomas Huth IEEE_ARITH2(cvtst)
713fcf5ef2aSThomas Huth IEEE_ARITH2(cvtts)
714fcf5ef2aSThomas Huth
715fcf5ef2aSThomas Huth static void gen_cvttq(DisasContext *ctx, int rb, int rc, int fn11)
716fcf5ef2aSThomas Huth {
717fcf5ef2aSThomas Huth TCGv vb, vc;
718fcf5ef2aSThomas Huth
719fcf5ef2aSThomas Huth /* No need to set flushzero, since we have an integer output. */
720fcf5ef2aSThomas Huth vb = gen_ieee_input(ctx, rb, fn11, 0);
721fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
722fcf5ef2aSThomas Huth
723fcf5ef2aSThomas Huth /* Almost all integer conversions use cropped rounding;
724fcf5ef2aSThomas Huth special case that. */
725fcf5ef2aSThomas Huth if ((fn11 & QUAL_RM_MASK) == QUAL_RM_C) {
726ad75a51eSRichard Henderson gen_helper_cvttq_c(vc, tcg_env, vb);
727fcf5ef2aSThomas Huth } else {
728fcf5ef2aSThomas Huth gen_qual_roundmode(ctx, fn11);
729ad75a51eSRichard Henderson gen_helper_cvttq(vc, tcg_env, vb);
730fcf5ef2aSThomas Huth }
731fcf5ef2aSThomas Huth gen_fp_exc_raise(rc, fn11);
732fcf5ef2aSThomas Huth }
733fcf5ef2aSThomas Huth
gen_ieee_intcvt(DisasContext * ctx,void (* helper)(TCGv,TCGv_ptr,TCGv),int rb,int rc,int fn11)734fcf5ef2aSThomas Huth static void gen_ieee_intcvt(DisasContext *ctx,
735fcf5ef2aSThomas Huth void (*helper)(TCGv, TCGv_ptr, TCGv),
736fcf5ef2aSThomas Huth int rb, int rc, int fn11)
737fcf5ef2aSThomas Huth {
738fcf5ef2aSThomas Huth TCGv vb, vc;
739fcf5ef2aSThomas Huth
740fcf5ef2aSThomas Huth gen_qual_roundmode(ctx, fn11);
741fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
742fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
743fcf5ef2aSThomas Huth
744fcf5ef2aSThomas Huth /* The only exception that can be raised by integer conversion
745fcf5ef2aSThomas Huth is inexact. Thus we only need to worry about exceptions when
746fcf5ef2aSThomas Huth inexact handling is requested. */
747fcf5ef2aSThomas Huth if (fn11 & QUAL_I) {
748ad75a51eSRichard Henderson helper(vc, tcg_env, vb);
749fcf5ef2aSThomas Huth gen_fp_exc_raise(rc, fn11);
750fcf5ef2aSThomas Huth } else {
751ad75a51eSRichard Henderson helper(vc, tcg_env, vb);
752fcf5ef2aSThomas Huth }
753fcf5ef2aSThomas Huth }
754fcf5ef2aSThomas Huth
755fcf5ef2aSThomas Huth #define IEEE_INTCVT(name) \
756fcf5ef2aSThomas Huth static inline void glue(gen_, name)(DisasContext *ctx, \
757fcf5ef2aSThomas Huth int rb, int rc, int fn11) \
758fcf5ef2aSThomas Huth { \
759fcf5ef2aSThomas Huth gen_ieee_intcvt(ctx, gen_helper_##name, rb, rc, fn11); \
760fcf5ef2aSThomas Huth }
761fcf5ef2aSThomas Huth IEEE_INTCVT(cvtqs)
IEEE_INTCVT(cvtqt)762fcf5ef2aSThomas Huth IEEE_INTCVT(cvtqt)
763fcf5ef2aSThomas Huth
764fcf5ef2aSThomas Huth static void gen_cpy_mask(TCGv vc, TCGv va, TCGv vb, bool inv_a, uint64_t mask)
765fcf5ef2aSThomas Huth {
766904bd855SRichard Henderson TCGv vmask = tcg_constant_i64(mask);
767fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new_i64();
768fcf5ef2aSThomas Huth
769fcf5ef2aSThomas Huth if (inv_a) {
770fcf5ef2aSThomas Huth tcg_gen_andc_i64(tmp, vmask, va);
771fcf5ef2aSThomas Huth } else {
772fcf5ef2aSThomas Huth tcg_gen_and_i64(tmp, va, vmask);
773fcf5ef2aSThomas Huth }
774fcf5ef2aSThomas Huth
775fcf5ef2aSThomas Huth tcg_gen_andc_i64(vc, vb, vmask);
776fcf5ef2aSThomas Huth tcg_gen_or_i64(vc, vc, tmp);
777fcf5ef2aSThomas Huth }
778fcf5ef2aSThomas Huth
gen_ieee_arith3(DisasContext * ctx,void (* helper)(TCGv,TCGv_ptr,TCGv,TCGv),int ra,int rb,int rc,int fn11)779fcf5ef2aSThomas Huth static void gen_ieee_arith3(DisasContext *ctx,
780fcf5ef2aSThomas Huth void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
781fcf5ef2aSThomas Huth int ra, int rb, int rc, int fn11)
782fcf5ef2aSThomas Huth {
783fcf5ef2aSThomas Huth TCGv va, vb, vc;
784fcf5ef2aSThomas Huth
785fcf5ef2aSThomas Huth gen_qual_roundmode(ctx, fn11);
786fcf5ef2aSThomas Huth gen_qual_flushzero(ctx, fn11);
787fcf5ef2aSThomas Huth
788fcf5ef2aSThomas Huth va = gen_ieee_input(ctx, ra, fn11, 0);
789fcf5ef2aSThomas Huth vb = gen_ieee_input(ctx, rb, fn11, 0);
790fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
791ad75a51eSRichard Henderson helper(vc, tcg_env, va, vb);
792fcf5ef2aSThomas Huth
793fcf5ef2aSThomas Huth gen_fp_exc_raise(rc, fn11);
794fcf5ef2aSThomas Huth }
795fcf5ef2aSThomas Huth
796fcf5ef2aSThomas Huth #define IEEE_ARITH3(name) \
797fcf5ef2aSThomas Huth static inline void glue(gen_, name)(DisasContext *ctx, \
798fcf5ef2aSThomas Huth int ra, int rb, int rc, int fn11) \
799fcf5ef2aSThomas Huth { \
800fcf5ef2aSThomas Huth gen_ieee_arith3(ctx, gen_helper_##name, ra, rb, rc, fn11); \
801fcf5ef2aSThomas Huth }
802fcf5ef2aSThomas Huth IEEE_ARITH3(adds)
IEEE_ARITH3(subs)803fcf5ef2aSThomas Huth IEEE_ARITH3(subs)
804fcf5ef2aSThomas Huth IEEE_ARITH3(muls)
805fcf5ef2aSThomas Huth IEEE_ARITH3(divs)
806fcf5ef2aSThomas Huth IEEE_ARITH3(addt)
807fcf5ef2aSThomas Huth IEEE_ARITH3(subt)
808fcf5ef2aSThomas Huth IEEE_ARITH3(mult)
809fcf5ef2aSThomas Huth IEEE_ARITH3(divt)
810fcf5ef2aSThomas Huth
811fcf5ef2aSThomas Huth static void gen_ieee_compare(DisasContext *ctx,
812fcf5ef2aSThomas Huth void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
813fcf5ef2aSThomas Huth int ra, int rb, int rc, int fn11)
814fcf5ef2aSThomas Huth {
815fcf5ef2aSThomas Huth TCGv va, vb, vc;
816fcf5ef2aSThomas Huth
817fcf5ef2aSThomas Huth va = gen_ieee_input(ctx, ra, fn11, 1);
818fcf5ef2aSThomas Huth vb = gen_ieee_input(ctx, rb, fn11, 1);
819fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
820ad75a51eSRichard Henderson helper(vc, tcg_env, va, vb);
821fcf5ef2aSThomas Huth
822fcf5ef2aSThomas Huth gen_fp_exc_raise(rc, fn11);
823fcf5ef2aSThomas Huth }
824fcf5ef2aSThomas Huth
825fcf5ef2aSThomas Huth #define IEEE_CMP3(name) \
826fcf5ef2aSThomas Huth static inline void glue(gen_, name)(DisasContext *ctx, \
827fcf5ef2aSThomas Huth int ra, int rb, int rc, int fn11) \
828fcf5ef2aSThomas Huth { \
829fcf5ef2aSThomas Huth gen_ieee_compare(ctx, gen_helper_##name, ra, rb, rc, fn11); \
830fcf5ef2aSThomas Huth }
831fcf5ef2aSThomas Huth IEEE_CMP3(cmptun)
IEEE_CMP3(cmpteq)832fcf5ef2aSThomas Huth IEEE_CMP3(cmpteq)
833fcf5ef2aSThomas Huth IEEE_CMP3(cmptlt)
834fcf5ef2aSThomas Huth IEEE_CMP3(cmptle)
835fcf5ef2aSThomas Huth
836fcf5ef2aSThomas Huth static inline uint64_t zapnot_mask(uint8_t lit)
837fcf5ef2aSThomas Huth {
838fcf5ef2aSThomas Huth uint64_t mask = 0;
839fcf5ef2aSThomas Huth int i;
840fcf5ef2aSThomas Huth
841fcf5ef2aSThomas Huth for (i = 0; i < 8; ++i) {
842fcf5ef2aSThomas Huth if ((lit >> i) & 1) {
843fcf5ef2aSThomas Huth mask |= 0xffull << (i * 8);
844fcf5ef2aSThomas Huth }
845fcf5ef2aSThomas Huth }
846fcf5ef2aSThomas Huth return mask;
847fcf5ef2aSThomas Huth }
848fcf5ef2aSThomas Huth
849fcf5ef2aSThomas Huth /* Implement zapnot with an immediate operand, which expands to some
850fcf5ef2aSThomas Huth form of immediate AND. This is a basic building block in the
851fcf5ef2aSThomas Huth definition of many of the other byte manipulation instructions. */
gen_zapnoti(TCGv dest,TCGv src,uint8_t lit)852fcf5ef2aSThomas Huth static void gen_zapnoti(TCGv dest, TCGv src, uint8_t lit)
853fcf5ef2aSThomas Huth {
854fcf5ef2aSThomas Huth switch (lit) {
855fcf5ef2aSThomas Huth case 0x00:
856fcf5ef2aSThomas Huth tcg_gen_movi_i64(dest, 0);
857fcf5ef2aSThomas Huth break;
858fcf5ef2aSThomas Huth case 0x01:
859fcf5ef2aSThomas Huth tcg_gen_ext8u_i64(dest, src);
860fcf5ef2aSThomas Huth break;
861fcf5ef2aSThomas Huth case 0x03:
862fcf5ef2aSThomas Huth tcg_gen_ext16u_i64(dest, src);
863fcf5ef2aSThomas Huth break;
864fcf5ef2aSThomas Huth case 0x0f:
865fcf5ef2aSThomas Huth tcg_gen_ext32u_i64(dest, src);
866fcf5ef2aSThomas Huth break;
867fcf5ef2aSThomas Huth case 0xff:
868fcf5ef2aSThomas Huth tcg_gen_mov_i64(dest, src);
869fcf5ef2aSThomas Huth break;
870fcf5ef2aSThomas Huth default:
871fcf5ef2aSThomas Huth tcg_gen_andi_i64(dest, src, zapnot_mask(lit));
872fcf5ef2aSThomas Huth break;
873fcf5ef2aSThomas Huth }
874fcf5ef2aSThomas Huth }
875fcf5ef2aSThomas Huth
876fcf5ef2aSThomas Huth /* EXTWH, EXTLH, EXTQH */
gen_ext_h(DisasContext * ctx,TCGv vc,TCGv va,int rb,bool islit,uint8_t lit,uint8_t byte_mask)877fcf5ef2aSThomas Huth static void gen_ext_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
878fcf5ef2aSThomas Huth uint8_t lit, uint8_t byte_mask)
879fcf5ef2aSThomas Huth {
880fcf5ef2aSThomas Huth if (islit) {
881f49f1ae7SRichard Henderson int pos = (64 - lit * 8) & 0x3f;
882f49f1ae7SRichard Henderson int len = cto32(byte_mask) * 8;
883f49f1ae7SRichard Henderson if (pos < len) {
884f49f1ae7SRichard Henderson tcg_gen_deposit_z_i64(vc, va, pos, len - pos);
885f49f1ae7SRichard Henderson } else {
886f49f1ae7SRichard Henderson tcg_gen_movi_i64(vc, 0);
887f49f1ae7SRichard Henderson }
888fcf5ef2aSThomas Huth } else {
889fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new();
890fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, load_gpr(ctx, rb), 3);
891fcf5ef2aSThomas Huth tcg_gen_neg_i64(tmp, tmp);
892fcf5ef2aSThomas Huth tcg_gen_andi_i64(tmp, tmp, 0x3f);
893fcf5ef2aSThomas Huth tcg_gen_shl_i64(vc, va, tmp);
894fcf5ef2aSThomas Huth }
895fcf5ef2aSThomas Huth gen_zapnoti(vc, vc, byte_mask);
896fcf5ef2aSThomas Huth }
897fcf5ef2aSThomas Huth
898fcf5ef2aSThomas Huth /* EXTBL, EXTWL, EXTLL, EXTQL */
gen_ext_l(DisasContext * ctx,TCGv vc,TCGv va,int rb,bool islit,uint8_t lit,uint8_t byte_mask)899fcf5ef2aSThomas Huth static void gen_ext_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
900fcf5ef2aSThomas Huth uint8_t lit, uint8_t byte_mask)
901fcf5ef2aSThomas Huth {
902fcf5ef2aSThomas Huth if (islit) {
903f49f1ae7SRichard Henderson int pos = (lit & 7) * 8;
904f49f1ae7SRichard Henderson int len = cto32(byte_mask) * 8;
905f49f1ae7SRichard Henderson if (pos + len >= 64) {
906f49f1ae7SRichard Henderson len = 64 - pos;
907f49f1ae7SRichard Henderson }
908f49f1ae7SRichard Henderson tcg_gen_extract_i64(vc, va, pos, len);
909fcf5ef2aSThomas Huth } else {
910fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new();
911fcf5ef2aSThomas Huth tcg_gen_andi_i64(tmp, load_gpr(ctx, rb), 7);
912fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, tmp, 3);
913fcf5ef2aSThomas Huth tcg_gen_shr_i64(vc, va, tmp);
914fcf5ef2aSThomas Huth gen_zapnoti(vc, vc, byte_mask);
915fcf5ef2aSThomas Huth }
916f49f1ae7SRichard Henderson }
917fcf5ef2aSThomas Huth
918fcf5ef2aSThomas Huth /* INSWH, INSLH, INSQH */
gen_ins_h(DisasContext * ctx,TCGv vc,TCGv va,int rb,bool islit,uint8_t lit,uint8_t byte_mask)919fcf5ef2aSThomas Huth static void gen_ins_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
920fcf5ef2aSThomas Huth uint8_t lit, uint8_t byte_mask)
921fcf5ef2aSThomas Huth {
922fcf5ef2aSThomas Huth if (islit) {
923f49f1ae7SRichard Henderson int pos = 64 - (lit & 7) * 8;
924f49f1ae7SRichard Henderson int len = cto32(byte_mask) * 8;
925f49f1ae7SRichard Henderson if (pos < len) {
926f49f1ae7SRichard Henderson tcg_gen_extract_i64(vc, va, pos, len - pos);
927fcf5ef2aSThomas Huth } else {
928f49f1ae7SRichard Henderson tcg_gen_movi_i64(vc, 0);
929fcf5ef2aSThomas Huth }
930fcf5ef2aSThomas Huth } else {
931f49f1ae7SRichard Henderson TCGv tmp = tcg_temp_new();
932fcf5ef2aSThomas Huth TCGv shift = tcg_temp_new();
933fcf5ef2aSThomas Huth
934f49f1ae7SRichard Henderson /* The instruction description has us left-shift the byte mask
935f49f1ae7SRichard Henderson and extract bits <15:8> and apply that zap at the end. This
936f49f1ae7SRichard Henderson is equivalent to simply performing the zap first and shifting
937f49f1ae7SRichard Henderson afterward. */
938f49f1ae7SRichard Henderson gen_zapnoti(tmp, va, byte_mask);
939f49f1ae7SRichard Henderson
940fcf5ef2aSThomas Huth /* If (B & 7) == 0, we need to shift by 64 and leave a zero. Do this
941fcf5ef2aSThomas Huth portably by splitting the shift into two parts: shift_count-1 and 1.
942fcf5ef2aSThomas Huth Arrange for the -1 by using ones-complement instead of
943fcf5ef2aSThomas Huth twos-complement in the negation: ~(B * 8) & 63. */
944fcf5ef2aSThomas Huth
945fcf5ef2aSThomas Huth tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
946fcf5ef2aSThomas Huth tcg_gen_not_i64(shift, shift);
947fcf5ef2aSThomas Huth tcg_gen_andi_i64(shift, shift, 0x3f);
948fcf5ef2aSThomas Huth
949fcf5ef2aSThomas Huth tcg_gen_shr_i64(vc, tmp, shift);
950fcf5ef2aSThomas Huth tcg_gen_shri_i64(vc, vc, 1);
951fcf5ef2aSThomas Huth }
952f49f1ae7SRichard Henderson }
953fcf5ef2aSThomas Huth
954fcf5ef2aSThomas Huth /* INSBL, INSWL, INSLL, INSQL */
gen_ins_l(DisasContext * ctx,TCGv vc,TCGv va,int rb,bool islit,uint8_t lit,uint8_t byte_mask)955fcf5ef2aSThomas Huth static void gen_ins_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
956fcf5ef2aSThomas Huth uint8_t lit, uint8_t byte_mask)
957fcf5ef2aSThomas Huth {
958f49f1ae7SRichard Henderson if (islit) {
959f49f1ae7SRichard Henderson int pos = (lit & 7) * 8;
960f49f1ae7SRichard Henderson int len = cto32(byte_mask) * 8;
961f49f1ae7SRichard Henderson if (pos + len > 64) {
962f49f1ae7SRichard Henderson len = 64 - pos;
963f49f1ae7SRichard Henderson }
964f49f1ae7SRichard Henderson tcg_gen_deposit_z_i64(vc, va, pos, len);
965f49f1ae7SRichard Henderson } else {
966fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new();
967f49f1ae7SRichard Henderson TCGv shift = tcg_temp_new();
968fcf5ef2aSThomas Huth
969fcf5ef2aSThomas Huth /* The instruction description has us left-shift the byte mask
970f49f1ae7SRichard Henderson and extract bits <15:8> and apply that zap at the end. This
971f49f1ae7SRichard Henderson is equivalent to simply performing the zap first and shifting
972f49f1ae7SRichard Henderson afterward. */
973fcf5ef2aSThomas Huth gen_zapnoti(tmp, va, byte_mask);
974fcf5ef2aSThomas Huth
975fcf5ef2aSThomas Huth tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
976fcf5ef2aSThomas Huth tcg_gen_shli_i64(shift, shift, 3);
977fcf5ef2aSThomas Huth tcg_gen_shl_i64(vc, tmp, shift);
978fcf5ef2aSThomas Huth }
979f49f1ae7SRichard Henderson }
980fcf5ef2aSThomas Huth
981fcf5ef2aSThomas Huth /* MSKWH, MSKLH, MSKQH */
gen_msk_h(DisasContext * ctx,TCGv vc,TCGv va,int rb,bool islit,uint8_t lit,uint8_t byte_mask)982fcf5ef2aSThomas Huth static void gen_msk_h(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
983fcf5ef2aSThomas Huth uint8_t lit, uint8_t byte_mask)
984fcf5ef2aSThomas Huth {
985fcf5ef2aSThomas Huth if (islit) {
986fcf5ef2aSThomas Huth gen_zapnoti(vc, va, ~((byte_mask << (lit & 7)) >> 8));
987fcf5ef2aSThomas Huth } else {
988fcf5ef2aSThomas Huth TCGv shift = tcg_temp_new();
989fcf5ef2aSThomas Huth TCGv mask = tcg_temp_new();
990fcf5ef2aSThomas Huth
991fcf5ef2aSThomas Huth /* The instruction description is as above, where the byte_mask
992fcf5ef2aSThomas Huth is shifted left, and then we extract bits <15:8>. This can be
993fcf5ef2aSThomas Huth emulated with a right-shift on the expanded byte mask. This
994fcf5ef2aSThomas Huth requires extra care because for an input <2:0> == 0 we need a
995fcf5ef2aSThomas Huth shift of 64 bits in order to generate a zero. This is done by
996fcf5ef2aSThomas Huth splitting the shift into two parts, the variable shift - 1
997fcf5ef2aSThomas Huth followed by a constant 1 shift. The code we expand below is
998fcf5ef2aSThomas Huth equivalent to ~(B * 8) & 63. */
999fcf5ef2aSThomas Huth
1000fcf5ef2aSThomas Huth tcg_gen_shli_i64(shift, load_gpr(ctx, rb), 3);
1001fcf5ef2aSThomas Huth tcg_gen_not_i64(shift, shift);
1002fcf5ef2aSThomas Huth tcg_gen_andi_i64(shift, shift, 0x3f);
1003fcf5ef2aSThomas Huth tcg_gen_movi_i64(mask, zapnot_mask (byte_mask));
1004fcf5ef2aSThomas Huth tcg_gen_shr_i64(mask, mask, shift);
1005fcf5ef2aSThomas Huth tcg_gen_shri_i64(mask, mask, 1);
1006fcf5ef2aSThomas Huth
1007fcf5ef2aSThomas Huth tcg_gen_andc_i64(vc, va, mask);
1008fcf5ef2aSThomas Huth }
1009fcf5ef2aSThomas Huth }
1010fcf5ef2aSThomas Huth
1011fcf5ef2aSThomas Huth /* MSKBL, MSKWL, MSKLL, MSKQL */
gen_msk_l(DisasContext * ctx,TCGv vc,TCGv va,int rb,bool islit,uint8_t lit,uint8_t byte_mask)1012fcf5ef2aSThomas Huth static void gen_msk_l(DisasContext *ctx, TCGv vc, TCGv va, int rb, bool islit,
1013fcf5ef2aSThomas Huth uint8_t lit, uint8_t byte_mask)
1014fcf5ef2aSThomas Huth {
1015fcf5ef2aSThomas Huth if (islit) {
1016fcf5ef2aSThomas Huth gen_zapnoti(vc, va, ~(byte_mask << (lit & 7)));
1017fcf5ef2aSThomas Huth } else {
1018fcf5ef2aSThomas Huth TCGv shift = tcg_temp_new();
1019fcf5ef2aSThomas Huth TCGv mask = tcg_temp_new();
1020fcf5ef2aSThomas Huth
1021fcf5ef2aSThomas Huth tcg_gen_andi_i64(shift, load_gpr(ctx, rb), 7);
1022fcf5ef2aSThomas Huth tcg_gen_shli_i64(shift, shift, 3);
1023fcf5ef2aSThomas Huth tcg_gen_movi_i64(mask, zapnot_mask(byte_mask));
1024fcf5ef2aSThomas Huth tcg_gen_shl_i64(mask, mask, shift);
1025fcf5ef2aSThomas Huth
1026fcf5ef2aSThomas Huth tcg_gen_andc_i64(vc, va, mask);
1027fcf5ef2aSThomas Huth }
1028fcf5ef2aSThomas Huth }
1029fcf5ef2aSThomas Huth
gen_rx(DisasContext * ctx,int ra,int set)1030fcf5ef2aSThomas Huth static void gen_rx(DisasContext *ctx, int ra, int set)
1031fcf5ef2aSThomas Huth {
1032fcf5ef2aSThomas Huth if (ra != 31) {
1033bcd2625dSRichard Henderson ld_flag_byte(ctx->ir[ra], ENV_FLAG_RX_SHIFT);
1034fcf5ef2aSThomas Huth }
1035fcf5ef2aSThomas Huth
1036492f85b9SRichard Henderson st_flag_byte(tcg_constant_i64(set), ENV_FLAG_RX_SHIFT);
1037fcf5ef2aSThomas Huth }
1038fcf5ef2aSThomas Huth
gen_call_pal(DisasContext * ctx,int palcode)10393de811c6SRichard Henderson static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
1040fcf5ef2aSThomas Huth {
1041fcf5ef2aSThomas Huth /* We're emulating OSF/1 PALcode. Many of these are trivial access
1042fcf5ef2aSThomas Huth to internal cpu registers. */
1043fcf5ef2aSThomas Huth
1044fcf5ef2aSThomas Huth /* Unprivileged PAL call */
1045fcf5ef2aSThomas Huth if (palcode >= 0x80 && palcode < 0xC0) {
1046fcf5ef2aSThomas Huth switch (palcode) {
1047fcf5ef2aSThomas Huth case 0x86:
1048fcf5ef2aSThomas Huth /* IMB */
1049fcf5ef2aSThomas Huth /* No-op inside QEMU. */
1050fcf5ef2aSThomas Huth break;
1051fcf5ef2aSThomas Huth case 0x9E:
1052fcf5ef2aSThomas Huth /* RDUNIQUE */
1053ad75a51eSRichard Henderson tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
1054fcf5ef2aSThomas Huth offsetof(CPUAlphaState, unique));
1055fcf5ef2aSThomas Huth break;
1056fcf5ef2aSThomas Huth case 0x9F:
1057fcf5ef2aSThomas Huth /* WRUNIQUE */
1058ad75a51eSRichard Henderson tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1059fcf5ef2aSThomas Huth offsetof(CPUAlphaState, unique));
1060fcf5ef2aSThomas Huth break;
1061fcf5ef2aSThomas Huth default:
1062fcf5ef2aSThomas Huth palcode &= 0xbf;
1063fcf5ef2aSThomas Huth goto do_call_pal;
1064fcf5ef2aSThomas Huth }
10653de811c6SRichard Henderson return DISAS_NEXT;
1066fcf5ef2aSThomas Huth }
1067fcf5ef2aSThomas Huth
1068fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
1069fcf5ef2aSThomas Huth /* Privileged PAL code */
1070bcd2625dSRichard Henderson if (palcode < 0x40 && (ctx->tbflags & ENV_FLAG_PS_USER) == 0) {
1071fcf5ef2aSThomas Huth switch (palcode) {
1072fcf5ef2aSThomas Huth case 0x01:
1073fcf5ef2aSThomas Huth /* CFLUSH */
1074fcf5ef2aSThomas Huth /* No-op inside QEMU. */
1075fcf5ef2aSThomas Huth break;
1076fcf5ef2aSThomas Huth case 0x02:
1077fcf5ef2aSThomas Huth /* DRAINA */
1078fcf5ef2aSThomas Huth /* No-op inside QEMU. */
1079fcf5ef2aSThomas Huth break;
1080fcf5ef2aSThomas Huth case 0x2D:
1081fcf5ef2aSThomas Huth /* WRVPTPTR */
1082ad75a51eSRichard Henderson tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1083fcf5ef2aSThomas Huth offsetof(CPUAlphaState, vptptr));
1084fcf5ef2aSThomas Huth break;
1085fcf5ef2aSThomas Huth case 0x31:
1086fcf5ef2aSThomas Huth /* WRVAL */
1087ad75a51eSRichard Henderson tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1088fcf5ef2aSThomas Huth offsetof(CPUAlphaState, sysval));
1089fcf5ef2aSThomas Huth break;
1090fcf5ef2aSThomas Huth case 0x32:
1091fcf5ef2aSThomas Huth /* RDVAL */
1092ad75a51eSRichard Henderson tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
1093fcf5ef2aSThomas Huth offsetof(CPUAlphaState, sysval));
1094fcf5ef2aSThomas Huth break;
1095fcf5ef2aSThomas Huth
1096bec5e2b9SRichard Henderson case 0x35:
1097fcf5ef2aSThomas Huth /* SWPIPL */
1098fcf5ef2aSThomas Huth /* Note that we already know we're in kernel mode, so we know
1099fcf5ef2aSThomas Huth that PS only contains the 3 IPL bits. */
1100bcd2625dSRichard Henderson ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
1101fcf5ef2aSThomas Huth
1102fcf5ef2aSThomas Huth /* But make sure and store only the 3 IPL bits from the user. */
1103f401c032SRichard Henderson {
1104f401c032SRichard Henderson TCGv tmp = tcg_temp_new();
1105fcf5ef2aSThomas Huth tcg_gen_andi_i64(tmp, ctx->ir[IR_A0], PS_INT_MASK);
1106bcd2625dSRichard Henderson st_flag_byte(tmp, ENV_FLAG_PS_SHIFT);
1107f401c032SRichard Henderson }
110854e1d4edSRichard Henderson
110954e1d4edSRichard Henderson /* Allow interrupts to be recognized right away. */
1110b1a3eacfSRichard Henderson gen_pc_disp(ctx, cpu_pc, 0);
11113de811c6SRichard Henderson return DISAS_PC_UPDATED_NOCHAIN;
1112fcf5ef2aSThomas Huth
1113fcf5ef2aSThomas Huth case 0x36:
1114fcf5ef2aSThomas Huth /* RDPS */
1115bcd2625dSRichard Henderson ld_flag_byte(ctx->ir[IR_V0], ENV_FLAG_PS_SHIFT);
1116fcf5ef2aSThomas Huth break;
1117bcd2625dSRichard Henderson
1118fcf5ef2aSThomas Huth case 0x38:
1119fcf5ef2aSThomas Huth /* WRUSP */
1120ad75a51eSRichard Henderson tcg_gen_st_i64(ctx->ir[IR_A0], tcg_env,
1121fcf5ef2aSThomas Huth offsetof(CPUAlphaState, usp));
1122fcf5ef2aSThomas Huth break;
1123fcf5ef2aSThomas Huth case 0x3A:
1124fcf5ef2aSThomas Huth /* RDUSP */
1125ad75a51eSRichard Henderson tcg_gen_ld_i64(ctx->ir[IR_V0], tcg_env,
1126fcf5ef2aSThomas Huth offsetof(CPUAlphaState, usp));
1127fcf5ef2aSThomas Huth break;
1128fcf5ef2aSThomas Huth case 0x3C:
1129fcf5ef2aSThomas Huth /* WHAMI */
1130ad75a51eSRichard Henderson tcg_gen_ld32s_i64(ctx->ir[IR_V0], tcg_env,
1131fcf5ef2aSThomas Huth -offsetof(AlphaCPU, env) + offsetof(CPUState, cpu_index));
1132fcf5ef2aSThomas Huth break;
1133fcf5ef2aSThomas Huth
1134bec5e2b9SRichard Henderson case 0x3E:
1135bec5e2b9SRichard Henderson /* WTINT */
1136ad75a51eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
1137904bd855SRichard Henderson -offsetof(AlphaCPU, env) +
1138bec5e2b9SRichard Henderson offsetof(CPUState, halted));
1139bec5e2b9SRichard Henderson tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
1140bec5e2b9SRichard Henderson return gen_excp(ctx, EXCP_HALTED, 0);
1141bec5e2b9SRichard Henderson
1142fcf5ef2aSThomas Huth default:
1143fcf5ef2aSThomas Huth palcode &= 0x3f;
1144fcf5ef2aSThomas Huth goto do_call_pal;
1145fcf5ef2aSThomas Huth }
11463de811c6SRichard Henderson return DISAS_NEXT;
1147fcf5ef2aSThomas Huth }
1148fcf5ef2aSThomas Huth #endif
1149fcf5ef2aSThomas Huth return gen_invalid(ctx);
1150fcf5ef2aSThomas Huth
1151fcf5ef2aSThomas Huth do_call_pal:
1152fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
1153fcf5ef2aSThomas Huth return gen_excp(ctx, EXCP_CALL_PAL, palcode);
1154fcf5ef2aSThomas Huth #else
1155fcf5ef2aSThomas Huth {
1156fcf5ef2aSThomas Huth TCGv tmp = tcg_temp_new();
1157b1a3eacfSRichard Henderson uint64_t entry;
1158fcf5ef2aSThomas Huth
1159b1a3eacfSRichard Henderson gen_pc_disp(ctx, tmp, 0);
1160bcd2625dSRichard Henderson if (ctx->tbflags & ENV_FLAG_PAL_MODE) {
1161b1a3eacfSRichard Henderson tcg_gen_ori_i64(tmp, tmp, 1);
1162fcf5ef2aSThomas Huth } else {
1163b1a3eacfSRichard Henderson st_flag_byte(tcg_constant_i64(1), ENV_FLAG_PAL_SHIFT);
1164fcf5ef2aSThomas Huth }
1165ad75a51eSRichard Henderson tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUAlphaState, exc_addr));
1166fcf5ef2aSThomas Huth
1167b1a3eacfSRichard Henderson entry = ctx->palbr;
1168fcf5ef2aSThomas Huth entry += (palcode & 0x80
1169fcf5ef2aSThomas Huth ? 0x2000 + (palcode - 0x80) * 64
1170fcf5ef2aSThomas Huth : 0x1000 + palcode * 64);
1171fcf5ef2aSThomas Huth
1172fcf5ef2aSThomas Huth tcg_gen_movi_i64(cpu_pc, entry);
11733de811c6SRichard Henderson return DISAS_PC_UPDATED;
1174fcf5ef2aSThomas Huth }
1175fcf5ef2aSThomas Huth #endif
1176fcf5ef2aSThomas Huth }
1177fcf5ef2aSThomas Huth
1178fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
1179fcf5ef2aSThomas Huth
1180fcf5ef2aSThomas Huth #define PR_LONG 0x200000
1181fcf5ef2aSThomas Huth
cpu_pr_data(int pr)1182fcf5ef2aSThomas Huth static int cpu_pr_data(int pr)
1183fcf5ef2aSThomas Huth {
1184fcf5ef2aSThomas Huth switch (pr) {
1185fcf5ef2aSThomas Huth case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
1186fcf5ef2aSThomas Huth case 3: return offsetof(CPUAlphaState, trap_arg0);
1187fcf5ef2aSThomas Huth case 4: return offsetof(CPUAlphaState, trap_arg1);
1188fcf5ef2aSThomas Huth case 5: return offsetof(CPUAlphaState, trap_arg2);
1189fcf5ef2aSThomas Huth case 6: return offsetof(CPUAlphaState, exc_addr);
1190fcf5ef2aSThomas Huth case 7: return offsetof(CPUAlphaState, palbr);
1191fcf5ef2aSThomas Huth case 8: return offsetof(CPUAlphaState, ptbr);
1192fcf5ef2aSThomas Huth case 9: return offsetof(CPUAlphaState, vptptr);
1193fcf5ef2aSThomas Huth case 10: return offsetof(CPUAlphaState, unique);
1194fcf5ef2aSThomas Huth case 11: return offsetof(CPUAlphaState, sysval);
1195fcf5ef2aSThomas Huth case 12: return offsetof(CPUAlphaState, usp);
1196fcf5ef2aSThomas Huth
1197fcf5ef2aSThomas Huth case 40 ... 63:
1198fcf5ef2aSThomas Huth return offsetof(CPUAlphaState, scratch[pr - 40]);
1199fcf5ef2aSThomas Huth
1200fcf5ef2aSThomas Huth case 251:
1201fcf5ef2aSThomas Huth return offsetof(CPUAlphaState, alarm_expire);
1202fcf5ef2aSThomas Huth }
1203fcf5ef2aSThomas Huth return 0;
1204fcf5ef2aSThomas Huth }
1205fcf5ef2aSThomas Huth
gen_mfpr(DisasContext * ctx,TCGv va,int regno)12063de811c6SRichard Henderson static DisasJumpType gen_mfpr(DisasContext *ctx, TCGv va, int regno)
1207fcf5ef2aSThomas Huth {
1208fcf5ef2aSThomas Huth void (*helper)(TCGv);
1209fcf5ef2aSThomas Huth int data;
1210fcf5ef2aSThomas Huth
1211fcf5ef2aSThomas Huth switch (regno) {
1212fcf5ef2aSThomas Huth case 32 ... 39:
1213fcf5ef2aSThomas Huth /* Accessing the "non-shadow" general registers. */
1214fcf5ef2aSThomas Huth regno = regno == 39 ? 25 : regno - 32 + 8;
1215fcf5ef2aSThomas Huth tcg_gen_mov_i64(va, cpu_std_ir[regno]);
1216fcf5ef2aSThomas Huth break;
1217fcf5ef2aSThomas Huth
1218fcf5ef2aSThomas Huth case 250: /* WALLTIME */
1219fcf5ef2aSThomas Huth helper = gen_helper_get_walltime;
1220fcf5ef2aSThomas Huth goto do_helper;
1221fcf5ef2aSThomas Huth case 249: /* VMTIME */
1222fcf5ef2aSThomas Huth helper = gen_helper_get_vmtime;
1223fcf5ef2aSThomas Huth do_helper:
1224dfd1b812SRichard Henderson if (translator_io_start(&ctx->base)) {
1225fcf5ef2aSThomas Huth helper(va);
12263de811c6SRichard Henderson return DISAS_PC_STALE;
1227fcf5ef2aSThomas Huth } else {
1228fcf5ef2aSThomas Huth helper(va);
1229fcf5ef2aSThomas Huth }
1230fcf5ef2aSThomas Huth break;
1231fcf5ef2aSThomas Huth
1232bcd2625dSRichard Henderson case 0: /* PS */
1233bcd2625dSRichard Henderson ld_flag_byte(va, ENV_FLAG_PS_SHIFT);
1234bcd2625dSRichard Henderson break;
1235bcd2625dSRichard Henderson case 1: /* FEN */
1236bcd2625dSRichard Henderson ld_flag_byte(va, ENV_FLAG_FEN_SHIFT);
1237bcd2625dSRichard Henderson break;
1238bcd2625dSRichard Henderson
1239fcf5ef2aSThomas Huth default:
1240fcf5ef2aSThomas Huth /* The basic registers are data only, and unknown registers
1241fcf5ef2aSThomas Huth are read-zero, write-ignore. */
1242fcf5ef2aSThomas Huth data = cpu_pr_data(regno);
1243fcf5ef2aSThomas Huth if (data == 0) {
1244fcf5ef2aSThomas Huth tcg_gen_movi_i64(va, 0);
1245fcf5ef2aSThomas Huth } else if (data & PR_LONG) {
1246ad75a51eSRichard Henderson tcg_gen_ld32s_i64(va, tcg_env, data & ~PR_LONG);
1247fcf5ef2aSThomas Huth } else {
1248ad75a51eSRichard Henderson tcg_gen_ld_i64(va, tcg_env, data);
1249fcf5ef2aSThomas Huth }
1250fcf5ef2aSThomas Huth break;
1251fcf5ef2aSThomas Huth }
1252fcf5ef2aSThomas Huth
12533de811c6SRichard Henderson return DISAS_NEXT;
1254fcf5ef2aSThomas Huth }
1255fcf5ef2aSThomas Huth
gen_mtpr(DisasContext * ctx,TCGv vb,int regno)12563de811c6SRichard Henderson static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, int regno)
1257fcf5ef2aSThomas Huth {
1258fcf5ef2aSThomas Huth int data;
1259ef951ee3SPavel Dovgalyuk DisasJumpType ret = DISAS_NEXT;
1260fcf5ef2aSThomas Huth
1261fcf5ef2aSThomas Huth switch (regno) {
1262fcf5ef2aSThomas Huth case 255:
1263fcf5ef2aSThomas Huth /* TBIA */
1264ad75a51eSRichard Henderson gen_helper_tbia(tcg_env);
1265fcf5ef2aSThomas Huth break;
1266fcf5ef2aSThomas Huth
1267fcf5ef2aSThomas Huth case 254:
1268fcf5ef2aSThomas Huth /* TBIS */
1269ad75a51eSRichard Henderson gen_helper_tbis(tcg_env, vb);
1270fcf5ef2aSThomas Huth break;
1271fcf5ef2aSThomas Huth
1272fcf5ef2aSThomas Huth case 253:
1273fcf5ef2aSThomas Huth /* WAIT */
1274ad75a51eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
1275904bd855SRichard Henderson -offsetof(AlphaCPU, env) + offsetof(CPUState, halted));
1276bec5e2b9SRichard Henderson return gen_excp(ctx, EXCP_HALTED, 0);
1277fcf5ef2aSThomas Huth
1278fcf5ef2aSThomas Huth case 252:
1279fcf5ef2aSThomas Huth /* HALT */
1280fcf5ef2aSThomas Huth gen_helper_halt(vb);
12813de811c6SRichard Henderson return DISAS_PC_STALE;
1282fcf5ef2aSThomas Huth
1283fcf5ef2aSThomas Huth case 251:
1284fcf5ef2aSThomas Huth /* ALARM */
1285dfd1b812SRichard Henderson if (translator_io_start(&ctx->base)) {
1286ef951ee3SPavel Dovgalyuk ret = DISAS_PC_STALE;
1287ef951ee3SPavel Dovgalyuk }
1288ad75a51eSRichard Henderson gen_helper_set_alarm(tcg_env, vb);
1289fcf5ef2aSThomas Huth break;
1290fcf5ef2aSThomas Huth
1291fcf5ef2aSThomas Huth case 7:
1292fcf5ef2aSThomas Huth /* PALBR */
1293ad75a51eSRichard Henderson tcg_gen_st_i64(vb, tcg_env, offsetof(CPUAlphaState, palbr));
1294fcf5ef2aSThomas Huth /* Changing the PAL base register implies un-chaining all of the TBs
1295fcf5ef2aSThomas Huth that ended with a CALL_PAL. Since the base register usually only
1296fcf5ef2aSThomas Huth changes during boot, flushing everything works well. */
1297ad75a51eSRichard Henderson gen_helper_tb_flush(tcg_env);
12983de811c6SRichard Henderson return DISAS_PC_STALE;
1299fcf5ef2aSThomas Huth
1300fcf5ef2aSThomas Huth case 32 ... 39:
1301fcf5ef2aSThomas Huth /* Accessing the "non-shadow" general registers. */
1302fcf5ef2aSThomas Huth regno = regno == 39 ? 25 : regno - 32 + 8;
1303fcf5ef2aSThomas Huth tcg_gen_mov_i64(cpu_std_ir[regno], vb);
1304fcf5ef2aSThomas Huth break;
1305fcf5ef2aSThomas Huth
1306bcd2625dSRichard Henderson case 0: /* PS */
1307bcd2625dSRichard Henderson st_flag_byte(vb, ENV_FLAG_PS_SHIFT);
1308bcd2625dSRichard Henderson break;
1309bcd2625dSRichard Henderson case 1: /* FEN */
1310bcd2625dSRichard Henderson st_flag_byte(vb, ENV_FLAG_FEN_SHIFT);
1311bcd2625dSRichard Henderson break;
1312bcd2625dSRichard Henderson
1313fcf5ef2aSThomas Huth default:
1314fcf5ef2aSThomas Huth /* The basic registers are data only, and unknown registers
1315fcf5ef2aSThomas Huth are read-zero, write-ignore. */
1316fcf5ef2aSThomas Huth data = cpu_pr_data(regno);
1317fcf5ef2aSThomas Huth if (data != 0) {
1318bcd2625dSRichard Henderson if (data & PR_LONG) {
1319ad75a51eSRichard Henderson tcg_gen_st32_i64(vb, tcg_env, data & ~PR_LONG);
1320fcf5ef2aSThomas Huth } else {
1321ad75a51eSRichard Henderson tcg_gen_st_i64(vb, tcg_env, data);
1322fcf5ef2aSThomas Huth }
1323fcf5ef2aSThomas Huth }
1324fcf5ef2aSThomas Huth break;
1325fcf5ef2aSThomas Huth }
1326fcf5ef2aSThomas Huth
1327ef951ee3SPavel Dovgalyuk return ret;
1328fcf5ef2aSThomas Huth }
1329fcf5ef2aSThomas Huth #endif /* !USER_ONLY*/
1330fcf5ef2aSThomas Huth
1331fcf5ef2aSThomas Huth #define REQUIRE_NO_LIT \
1332fcf5ef2aSThomas Huth do { \
1333fcf5ef2aSThomas Huth if (real_islit) { \
1334fcf5ef2aSThomas Huth goto invalid_opc; \
1335fcf5ef2aSThomas Huth } \
1336fcf5ef2aSThomas Huth } while (0)
1337fcf5ef2aSThomas Huth
1338c6d41b36SRichard Henderson #define REQUIRE_AMASK(FLAG) \
1339c6d41b36SRichard Henderson do { \
1340c6d41b36SRichard Henderson if ((ctx->amask & AMASK_##FLAG) == 0) { \
1341c6d41b36SRichard Henderson goto invalid_opc; \
1342c6d41b36SRichard Henderson } \
1343c6d41b36SRichard Henderson } while (0)
1344c6d41b36SRichard Henderson
1345fcf5ef2aSThomas Huth #define REQUIRE_TB_FLAG(FLAG) \
1346fcf5ef2aSThomas Huth do { \
1347489a0e64SRichard Henderson if ((ctx->tbflags & (FLAG)) == 0) { \
1348fcf5ef2aSThomas Huth goto invalid_opc; \
1349fcf5ef2aSThomas Huth } \
1350fcf5ef2aSThomas Huth } while (0)
1351fcf5ef2aSThomas Huth
1352fcf5ef2aSThomas Huth #define REQUIRE_REG_31(WHICH) \
1353fcf5ef2aSThomas Huth do { \
1354fcf5ef2aSThomas Huth if (WHICH != 31) { \
1355fcf5ef2aSThomas Huth goto invalid_opc; \
1356fcf5ef2aSThomas Huth } \
1357fcf5ef2aSThomas Huth } while (0)
1358fcf5ef2aSThomas Huth
13599d14a042SRichard Henderson #define REQUIRE_FEN \
13609d14a042SRichard Henderson do { \
13619d14a042SRichard Henderson if (!(ctx->tbflags & ENV_FLAG_FEN)) { \
13629d14a042SRichard Henderson goto raise_fen; \
13639d14a042SRichard Henderson } \
13649d14a042SRichard Henderson } while (0)
13659d14a042SRichard Henderson
translate_one(DisasContext * ctx,uint32_t insn)13663de811c6SRichard Henderson static DisasJumpType translate_one(DisasContext *ctx, uint32_t insn)
1367fcf5ef2aSThomas Huth {
1368fcf5ef2aSThomas Huth int32_t disp21, disp16, disp12 __attribute__((unused));
1369fcf5ef2aSThomas Huth uint16_t fn11;
1370fcf5ef2aSThomas Huth uint8_t opc, ra, rb, rc, fpfn, fn7, lit;
1371fcf5ef2aSThomas Huth bool islit, real_islit;
1372fcf5ef2aSThomas Huth TCGv va, vb, vc, tmp, tmp2;
1373fcf5ef2aSThomas Huth TCGv_i32 t32;
13743de811c6SRichard Henderson DisasJumpType ret;
1375fcf5ef2aSThomas Huth
1376fcf5ef2aSThomas Huth /* Decode all instruction fields */
1377fcf5ef2aSThomas Huth opc = extract32(insn, 26, 6);
1378fcf5ef2aSThomas Huth ra = extract32(insn, 21, 5);
1379fcf5ef2aSThomas Huth rb = extract32(insn, 16, 5);
1380fcf5ef2aSThomas Huth rc = extract32(insn, 0, 5);
1381fcf5ef2aSThomas Huth real_islit = islit = extract32(insn, 12, 1);
1382fcf5ef2aSThomas Huth lit = extract32(insn, 13, 8);
1383fcf5ef2aSThomas Huth
13841bcae46aSRichard Henderson disp21 = sextract32(insn, 0, 21) * 4;
1385fcf5ef2aSThomas Huth disp16 = sextract32(insn, 0, 16);
1386fcf5ef2aSThomas Huth disp12 = sextract32(insn, 0, 12);
1387fcf5ef2aSThomas Huth
1388fcf5ef2aSThomas Huth fn11 = extract32(insn, 5, 11);
1389fcf5ef2aSThomas Huth fpfn = extract32(insn, 5, 6);
1390fcf5ef2aSThomas Huth fn7 = extract32(insn, 5, 7);
1391fcf5ef2aSThomas Huth
1392fcf5ef2aSThomas Huth if (rb == 31 && !islit) {
1393fcf5ef2aSThomas Huth islit = true;
1394fcf5ef2aSThomas Huth lit = 0;
1395fcf5ef2aSThomas Huth }
1396fcf5ef2aSThomas Huth
13973de811c6SRichard Henderson ret = DISAS_NEXT;
1398fcf5ef2aSThomas Huth switch (opc) {
1399fcf5ef2aSThomas Huth case 0x00:
1400fcf5ef2aSThomas Huth /* CALL_PAL */
1401fcf5ef2aSThomas Huth ret = gen_call_pal(ctx, insn & 0x03ffffff);
1402fcf5ef2aSThomas Huth break;
1403fcf5ef2aSThomas Huth case 0x01:
1404fcf5ef2aSThomas Huth /* OPC01 */
1405fcf5ef2aSThomas Huth goto invalid_opc;
1406fcf5ef2aSThomas Huth case 0x02:
1407fcf5ef2aSThomas Huth /* OPC02 */
1408fcf5ef2aSThomas Huth goto invalid_opc;
1409fcf5ef2aSThomas Huth case 0x03:
1410fcf5ef2aSThomas Huth /* OPC03 */
1411fcf5ef2aSThomas Huth goto invalid_opc;
1412fcf5ef2aSThomas Huth case 0x04:
1413fcf5ef2aSThomas Huth /* OPC04 */
1414fcf5ef2aSThomas Huth goto invalid_opc;
1415fcf5ef2aSThomas Huth case 0x05:
1416fcf5ef2aSThomas Huth /* OPC05 */
1417fcf5ef2aSThomas Huth goto invalid_opc;
1418fcf5ef2aSThomas Huth case 0x06:
1419fcf5ef2aSThomas Huth /* OPC06 */
1420fcf5ef2aSThomas Huth goto invalid_opc;
1421fcf5ef2aSThomas Huth case 0x07:
1422fcf5ef2aSThomas Huth /* OPC07 */
1423fcf5ef2aSThomas Huth goto invalid_opc;
1424fcf5ef2aSThomas Huth
1425fcf5ef2aSThomas Huth case 0x09:
1426fcf5ef2aSThomas Huth /* LDAH */
1427fcf5ef2aSThomas Huth disp16 = (uint32_t)disp16 << 16;
1428fcf5ef2aSThomas Huth /* fall through */
1429fcf5ef2aSThomas Huth case 0x08:
1430fcf5ef2aSThomas Huth /* LDA */
1431fcf5ef2aSThomas Huth va = dest_gpr(ctx, ra);
1432fcf5ef2aSThomas Huth /* It's worth special-casing immediate loads. */
1433fcf5ef2aSThomas Huth if (rb == 31) {
1434fcf5ef2aSThomas Huth tcg_gen_movi_i64(va, disp16);
1435fcf5ef2aSThomas Huth } else {
1436fcf5ef2aSThomas Huth tcg_gen_addi_i64(va, load_gpr(ctx, rb), disp16);
1437fcf5ef2aSThomas Huth }
1438fcf5ef2aSThomas Huth break;
1439fcf5ef2aSThomas Huth
1440fcf5ef2aSThomas Huth case 0x0A:
1441fcf5ef2aSThomas Huth /* LDBU */
1442c6d41b36SRichard Henderson REQUIRE_AMASK(BWX);
14435ffcb334SRichard Henderson gen_load_int(ctx, ra, rb, disp16, MO_UB, 0, 0);
1444fcf5ef2aSThomas Huth break;
1445fcf5ef2aSThomas Huth case 0x0B:
1446fcf5ef2aSThomas Huth /* LDQ_U */
1447fc313c64SFrédéric Pétrot gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 1, 0);
1448fcf5ef2aSThomas Huth break;
1449fcf5ef2aSThomas Huth case 0x0C:
1450fcf5ef2aSThomas Huth /* LDWU */
1451c6d41b36SRichard Henderson REQUIRE_AMASK(BWX);
14525ffcb334SRichard Henderson gen_load_int(ctx, ra, rb, disp16, MO_LEUW, 0, 0);
1453fcf5ef2aSThomas Huth break;
1454fcf5ef2aSThomas Huth case 0x0D:
1455fcf5ef2aSThomas Huth /* STW */
1456c6d41b36SRichard Henderson REQUIRE_AMASK(BWX);
14575ffcb334SRichard Henderson gen_store_int(ctx, ra, rb, disp16, MO_LEUW, 0);
1458fcf5ef2aSThomas Huth break;
1459fcf5ef2aSThomas Huth case 0x0E:
1460fcf5ef2aSThomas Huth /* STB */
1461c6d41b36SRichard Henderson REQUIRE_AMASK(BWX);
14625ffcb334SRichard Henderson gen_store_int(ctx, ra, rb, disp16, MO_UB, 0);
1463fcf5ef2aSThomas Huth break;
1464fcf5ef2aSThomas Huth case 0x0F:
1465fcf5ef2aSThomas Huth /* STQ_U */
1466fc313c64SFrédéric Pétrot gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 1);
1467fcf5ef2aSThomas Huth break;
1468fcf5ef2aSThomas Huth
1469fcf5ef2aSThomas Huth case 0x10:
1470fcf5ef2aSThomas Huth vc = dest_gpr(ctx, rc);
1471fcf5ef2aSThomas Huth vb = load_gpr_lit(ctx, rb, lit, islit);
1472fcf5ef2aSThomas Huth
1473fcf5ef2aSThomas Huth if (ra == 31) {
1474fcf5ef2aSThomas Huth if (fn7 == 0x00) {
1475fcf5ef2aSThomas Huth /* Special case ADDL as SEXTL. */
1476fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, vb);
1477fcf5ef2aSThomas Huth break;
1478fcf5ef2aSThomas Huth }
1479fcf5ef2aSThomas Huth if (fn7 == 0x29) {
1480fcf5ef2aSThomas Huth /* Special case SUBQ as NEGQ. */
1481fcf5ef2aSThomas Huth tcg_gen_neg_i64(vc, vb);
1482fcf5ef2aSThomas Huth break;
1483fcf5ef2aSThomas Huth }
1484fcf5ef2aSThomas Huth }
1485fcf5ef2aSThomas Huth
1486fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
1487fcf5ef2aSThomas Huth switch (fn7) {
1488fcf5ef2aSThomas Huth case 0x00:
1489fcf5ef2aSThomas Huth /* ADDL */
1490fcf5ef2aSThomas Huth tcg_gen_add_i64(vc, va, vb);
1491fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, vc);
1492fcf5ef2aSThomas Huth break;
1493fcf5ef2aSThomas Huth case 0x02:
1494fcf5ef2aSThomas Huth /* S4ADDL */
1495fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1496fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 2);
1497fcf5ef2aSThomas Huth tcg_gen_add_i64(tmp, tmp, vb);
1498fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, tmp);
1499fcf5ef2aSThomas Huth break;
1500fcf5ef2aSThomas Huth case 0x09:
1501fcf5ef2aSThomas Huth /* SUBL */
1502fcf5ef2aSThomas Huth tcg_gen_sub_i64(vc, va, vb);
1503fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, vc);
1504fcf5ef2aSThomas Huth break;
1505fcf5ef2aSThomas Huth case 0x0B:
1506fcf5ef2aSThomas Huth /* S4SUBL */
1507fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1508fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 2);
1509fcf5ef2aSThomas Huth tcg_gen_sub_i64(tmp, tmp, vb);
1510fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, tmp);
1511fcf5ef2aSThomas Huth break;
1512fcf5ef2aSThomas Huth case 0x0F:
1513fcf5ef2aSThomas Huth /* CMPBGE */
1514fcf5ef2aSThomas Huth if (ra == 31) {
1515fcf5ef2aSThomas Huth /* Special case 0 >= X as X == 0. */
1516fcf5ef2aSThomas Huth gen_helper_cmpbe0(vc, vb);
1517fcf5ef2aSThomas Huth } else {
1518fcf5ef2aSThomas Huth gen_helper_cmpbge(vc, va, vb);
1519fcf5ef2aSThomas Huth }
1520fcf5ef2aSThomas Huth break;
1521fcf5ef2aSThomas Huth case 0x12:
1522fcf5ef2aSThomas Huth /* S8ADDL */
1523fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1524fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 3);
1525fcf5ef2aSThomas Huth tcg_gen_add_i64(tmp, tmp, vb);
1526fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, tmp);
1527fcf5ef2aSThomas Huth break;
1528fcf5ef2aSThomas Huth case 0x1B:
1529fcf5ef2aSThomas Huth /* S8SUBL */
1530fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1531fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 3);
1532fcf5ef2aSThomas Huth tcg_gen_sub_i64(tmp, tmp, vb);
1533fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, tmp);
1534fcf5ef2aSThomas Huth break;
1535fcf5ef2aSThomas Huth case 0x1D:
1536fcf5ef2aSThomas Huth /* CMPULT */
1537fcf5ef2aSThomas Huth tcg_gen_setcond_i64(TCG_COND_LTU, vc, va, vb);
1538fcf5ef2aSThomas Huth break;
1539fcf5ef2aSThomas Huth case 0x20:
1540fcf5ef2aSThomas Huth /* ADDQ */
1541fcf5ef2aSThomas Huth tcg_gen_add_i64(vc, va, vb);
1542fcf5ef2aSThomas Huth break;
1543fcf5ef2aSThomas Huth case 0x22:
1544fcf5ef2aSThomas Huth /* S4ADDQ */
1545fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1546fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 2);
1547fcf5ef2aSThomas Huth tcg_gen_add_i64(vc, tmp, vb);
1548fcf5ef2aSThomas Huth break;
1549fcf5ef2aSThomas Huth case 0x29:
1550fcf5ef2aSThomas Huth /* SUBQ */
1551fcf5ef2aSThomas Huth tcg_gen_sub_i64(vc, va, vb);
1552fcf5ef2aSThomas Huth break;
1553fcf5ef2aSThomas Huth case 0x2B:
1554fcf5ef2aSThomas Huth /* S4SUBQ */
1555fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1556fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 2);
1557fcf5ef2aSThomas Huth tcg_gen_sub_i64(vc, tmp, vb);
1558fcf5ef2aSThomas Huth break;
1559fcf5ef2aSThomas Huth case 0x2D:
1560fcf5ef2aSThomas Huth /* CMPEQ */
1561fcf5ef2aSThomas Huth tcg_gen_setcond_i64(TCG_COND_EQ, vc, va, vb);
1562fcf5ef2aSThomas Huth break;
1563fcf5ef2aSThomas Huth case 0x32:
1564fcf5ef2aSThomas Huth /* S8ADDQ */
1565fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1566fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 3);
1567fcf5ef2aSThomas Huth tcg_gen_add_i64(vc, tmp, vb);
1568fcf5ef2aSThomas Huth break;
1569fcf5ef2aSThomas Huth case 0x3B:
1570fcf5ef2aSThomas Huth /* S8SUBQ */
1571fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1572fcf5ef2aSThomas Huth tcg_gen_shli_i64(tmp, va, 3);
1573fcf5ef2aSThomas Huth tcg_gen_sub_i64(vc, tmp, vb);
1574fcf5ef2aSThomas Huth break;
1575fcf5ef2aSThomas Huth case 0x3D:
1576fcf5ef2aSThomas Huth /* CMPULE */
1577fcf5ef2aSThomas Huth tcg_gen_setcond_i64(TCG_COND_LEU, vc, va, vb);
1578fcf5ef2aSThomas Huth break;
1579fcf5ef2aSThomas Huth case 0x40:
1580fcf5ef2aSThomas Huth /* ADDL/V */
1581fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1582fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(tmp, va);
1583fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, vb);
1584fcf5ef2aSThomas Huth tcg_gen_add_i64(tmp, tmp, vc);
1585fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, tmp);
1586ad75a51eSRichard Henderson gen_helper_check_overflow(tcg_env, vc, tmp);
1587fcf5ef2aSThomas Huth break;
1588fcf5ef2aSThomas Huth case 0x49:
1589fcf5ef2aSThomas Huth /* SUBL/V */
1590fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1591fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(tmp, va);
1592fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, vb);
1593fcf5ef2aSThomas Huth tcg_gen_sub_i64(tmp, tmp, vc);
1594fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, tmp);
1595ad75a51eSRichard Henderson gen_helper_check_overflow(tcg_env, vc, tmp);
1596fcf5ef2aSThomas Huth break;
1597fcf5ef2aSThomas Huth case 0x4D:
1598fcf5ef2aSThomas Huth /* CMPLT */
1599fcf5ef2aSThomas Huth tcg_gen_setcond_i64(TCG_COND_LT, vc, va, vb);
1600fcf5ef2aSThomas Huth break;
1601fcf5ef2aSThomas Huth case 0x60:
1602fcf5ef2aSThomas Huth /* ADDQ/V */
1603fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1604fcf5ef2aSThomas Huth tmp2 = tcg_temp_new();
1605fcf5ef2aSThomas Huth tcg_gen_eqv_i64(tmp, va, vb);
1606fcf5ef2aSThomas Huth tcg_gen_mov_i64(tmp2, va);
1607fcf5ef2aSThomas Huth tcg_gen_add_i64(vc, va, vb);
1608fcf5ef2aSThomas Huth tcg_gen_xor_i64(tmp2, tmp2, vc);
1609fcf5ef2aSThomas Huth tcg_gen_and_i64(tmp, tmp, tmp2);
1610fcf5ef2aSThomas Huth tcg_gen_shri_i64(tmp, tmp, 63);
1611fcf5ef2aSThomas Huth tcg_gen_movi_i64(tmp2, 0);
1612ad75a51eSRichard Henderson gen_helper_check_overflow(tcg_env, tmp, tmp2);
1613fcf5ef2aSThomas Huth break;
1614fcf5ef2aSThomas Huth case 0x69:
1615fcf5ef2aSThomas Huth /* SUBQ/V */
1616fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1617fcf5ef2aSThomas Huth tmp2 = tcg_temp_new();
1618fcf5ef2aSThomas Huth tcg_gen_xor_i64(tmp, va, vb);
1619fcf5ef2aSThomas Huth tcg_gen_mov_i64(tmp2, va);
1620fcf5ef2aSThomas Huth tcg_gen_sub_i64(vc, va, vb);
1621fcf5ef2aSThomas Huth tcg_gen_xor_i64(tmp2, tmp2, vc);
1622fcf5ef2aSThomas Huth tcg_gen_and_i64(tmp, tmp, tmp2);
1623fcf5ef2aSThomas Huth tcg_gen_shri_i64(tmp, tmp, 63);
1624fcf5ef2aSThomas Huth tcg_gen_movi_i64(tmp2, 0);
1625ad75a51eSRichard Henderson gen_helper_check_overflow(tcg_env, tmp, tmp2);
1626fcf5ef2aSThomas Huth break;
1627fcf5ef2aSThomas Huth case 0x6D:
1628fcf5ef2aSThomas Huth /* CMPLE */
1629fcf5ef2aSThomas Huth tcg_gen_setcond_i64(TCG_COND_LE, vc, va, vb);
1630fcf5ef2aSThomas Huth break;
1631fcf5ef2aSThomas Huth default:
1632fcf5ef2aSThomas Huth goto invalid_opc;
1633fcf5ef2aSThomas Huth }
1634fcf5ef2aSThomas Huth break;
1635fcf5ef2aSThomas Huth
1636fcf5ef2aSThomas Huth case 0x11:
1637fcf5ef2aSThomas Huth if (fn7 == 0x20) {
1638fcf5ef2aSThomas Huth if (rc == 31) {
1639fcf5ef2aSThomas Huth /* Special case BIS as NOP. */
1640fcf5ef2aSThomas Huth break;
1641fcf5ef2aSThomas Huth }
1642fcf5ef2aSThomas Huth if (ra == 31) {
1643fcf5ef2aSThomas Huth /* Special case BIS as MOV. */
1644fcf5ef2aSThomas Huth vc = dest_gpr(ctx, rc);
1645fcf5ef2aSThomas Huth if (islit) {
1646fcf5ef2aSThomas Huth tcg_gen_movi_i64(vc, lit);
1647fcf5ef2aSThomas Huth } else {
1648fcf5ef2aSThomas Huth tcg_gen_mov_i64(vc, load_gpr(ctx, rb));
1649fcf5ef2aSThomas Huth }
1650fcf5ef2aSThomas Huth break;
1651fcf5ef2aSThomas Huth }
1652fcf5ef2aSThomas Huth }
1653fcf5ef2aSThomas Huth
1654fcf5ef2aSThomas Huth vc = dest_gpr(ctx, rc);
1655fcf5ef2aSThomas Huth vb = load_gpr_lit(ctx, rb, lit, islit);
1656fcf5ef2aSThomas Huth
1657fcf5ef2aSThomas Huth if (fn7 == 0x28 && ra == 31) {
1658fcf5ef2aSThomas Huth /* Special case ORNOT as NOT. */
1659fcf5ef2aSThomas Huth tcg_gen_not_i64(vc, vb);
1660fcf5ef2aSThomas Huth break;
1661fcf5ef2aSThomas Huth }
1662fcf5ef2aSThomas Huth
1663fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
1664fcf5ef2aSThomas Huth switch (fn7) {
1665fcf5ef2aSThomas Huth case 0x00:
1666fcf5ef2aSThomas Huth /* AND */
1667fcf5ef2aSThomas Huth tcg_gen_and_i64(vc, va, vb);
1668fcf5ef2aSThomas Huth break;
1669fcf5ef2aSThomas Huth case 0x08:
1670fcf5ef2aSThomas Huth /* BIC */
1671fcf5ef2aSThomas Huth tcg_gen_andc_i64(vc, va, vb);
1672fcf5ef2aSThomas Huth break;
1673fcf5ef2aSThomas Huth case 0x14:
1674fcf5ef2aSThomas Huth /* CMOVLBS */
1675c47341f1SRichard Henderson tcg_gen_movcond_i64(TCG_COND_TSTNE, vc, va, tcg_constant_i64(1),
1676fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1677fcf5ef2aSThomas Huth break;
1678fcf5ef2aSThomas Huth case 0x16:
1679fcf5ef2aSThomas Huth /* CMOVLBC */
1680c47341f1SRichard Henderson tcg_gen_movcond_i64(TCG_COND_TSTEQ, vc, va, tcg_constant_i64(1),
1681fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1682fcf5ef2aSThomas Huth break;
1683fcf5ef2aSThomas Huth case 0x20:
1684fcf5ef2aSThomas Huth /* BIS */
1685fcf5ef2aSThomas Huth tcg_gen_or_i64(vc, va, vb);
1686fcf5ef2aSThomas Huth break;
1687fcf5ef2aSThomas Huth case 0x24:
1688fcf5ef2aSThomas Huth /* CMOVEQ */
1689fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_EQ, vc, va, load_zero(ctx),
1690fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1691fcf5ef2aSThomas Huth break;
1692fcf5ef2aSThomas Huth case 0x26:
1693fcf5ef2aSThomas Huth /* CMOVNE */
1694fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_NE, vc, va, load_zero(ctx),
1695fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1696fcf5ef2aSThomas Huth break;
1697fcf5ef2aSThomas Huth case 0x28:
1698fcf5ef2aSThomas Huth /* ORNOT */
1699fcf5ef2aSThomas Huth tcg_gen_orc_i64(vc, va, vb);
1700fcf5ef2aSThomas Huth break;
1701fcf5ef2aSThomas Huth case 0x40:
1702fcf5ef2aSThomas Huth /* XOR */
1703fcf5ef2aSThomas Huth tcg_gen_xor_i64(vc, va, vb);
1704fcf5ef2aSThomas Huth break;
1705fcf5ef2aSThomas Huth case 0x44:
1706fcf5ef2aSThomas Huth /* CMOVLT */
1707fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_LT, vc, va, load_zero(ctx),
1708fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1709fcf5ef2aSThomas Huth break;
1710fcf5ef2aSThomas Huth case 0x46:
1711fcf5ef2aSThomas Huth /* CMOVGE */
1712fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_GE, vc, va, load_zero(ctx),
1713fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1714fcf5ef2aSThomas Huth break;
1715fcf5ef2aSThomas Huth case 0x48:
1716fcf5ef2aSThomas Huth /* EQV */
1717fcf5ef2aSThomas Huth tcg_gen_eqv_i64(vc, va, vb);
1718fcf5ef2aSThomas Huth break;
1719fcf5ef2aSThomas Huth case 0x61:
1720fcf5ef2aSThomas Huth /* AMASK */
1721fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
1722c6d41b36SRichard Henderson tcg_gen_andi_i64(vc, vb, ~ctx->amask);
1723fcf5ef2aSThomas Huth break;
1724fcf5ef2aSThomas Huth case 0x64:
1725fcf5ef2aSThomas Huth /* CMOVLE */
1726fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_LE, vc, va, load_zero(ctx),
1727fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1728fcf5ef2aSThomas Huth break;
1729fcf5ef2aSThomas Huth case 0x66:
1730fcf5ef2aSThomas Huth /* CMOVGT */
1731fcf5ef2aSThomas Huth tcg_gen_movcond_i64(TCG_COND_GT, vc, va, load_zero(ctx),
1732fcf5ef2aSThomas Huth vb, load_gpr(ctx, rc));
1733fcf5ef2aSThomas Huth break;
1734fcf5ef2aSThomas Huth case 0x6C:
1735fcf5ef2aSThomas Huth /* IMPLVER */
1736fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
1737fcf5ef2aSThomas Huth tcg_gen_movi_i64(vc, ctx->implver);
1738fcf5ef2aSThomas Huth break;
1739fcf5ef2aSThomas Huth default:
1740fcf5ef2aSThomas Huth goto invalid_opc;
1741fcf5ef2aSThomas Huth }
1742fcf5ef2aSThomas Huth break;
1743fcf5ef2aSThomas Huth
1744fcf5ef2aSThomas Huth case 0x12:
1745fcf5ef2aSThomas Huth vc = dest_gpr(ctx, rc);
1746fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
1747fcf5ef2aSThomas Huth switch (fn7) {
1748fcf5ef2aSThomas Huth case 0x02:
1749fcf5ef2aSThomas Huth /* MSKBL */
1750fcf5ef2aSThomas Huth gen_msk_l(ctx, vc, va, rb, islit, lit, 0x01);
1751fcf5ef2aSThomas Huth break;
1752fcf5ef2aSThomas Huth case 0x06:
1753fcf5ef2aSThomas Huth /* EXTBL */
1754fcf5ef2aSThomas Huth gen_ext_l(ctx, vc, va, rb, islit, lit, 0x01);
1755fcf5ef2aSThomas Huth break;
1756fcf5ef2aSThomas Huth case 0x0B:
1757fcf5ef2aSThomas Huth /* INSBL */
1758fcf5ef2aSThomas Huth gen_ins_l(ctx, vc, va, rb, islit, lit, 0x01);
1759fcf5ef2aSThomas Huth break;
1760fcf5ef2aSThomas Huth case 0x12:
1761fcf5ef2aSThomas Huth /* MSKWL */
1762fcf5ef2aSThomas Huth gen_msk_l(ctx, vc, va, rb, islit, lit, 0x03);
1763fcf5ef2aSThomas Huth break;
1764fcf5ef2aSThomas Huth case 0x16:
1765fcf5ef2aSThomas Huth /* EXTWL */
1766fcf5ef2aSThomas Huth gen_ext_l(ctx, vc, va, rb, islit, lit, 0x03);
1767fcf5ef2aSThomas Huth break;
1768fcf5ef2aSThomas Huth case 0x1B:
1769fcf5ef2aSThomas Huth /* INSWL */
1770fcf5ef2aSThomas Huth gen_ins_l(ctx, vc, va, rb, islit, lit, 0x03);
1771fcf5ef2aSThomas Huth break;
1772fcf5ef2aSThomas Huth case 0x22:
1773fcf5ef2aSThomas Huth /* MSKLL */
1774fcf5ef2aSThomas Huth gen_msk_l(ctx, vc, va, rb, islit, lit, 0x0f);
1775fcf5ef2aSThomas Huth break;
1776fcf5ef2aSThomas Huth case 0x26:
1777fcf5ef2aSThomas Huth /* EXTLL */
1778fcf5ef2aSThomas Huth gen_ext_l(ctx, vc, va, rb, islit, lit, 0x0f);
1779fcf5ef2aSThomas Huth break;
1780fcf5ef2aSThomas Huth case 0x2B:
1781fcf5ef2aSThomas Huth /* INSLL */
1782fcf5ef2aSThomas Huth gen_ins_l(ctx, vc, va, rb, islit, lit, 0x0f);
1783fcf5ef2aSThomas Huth break;
1784fcf5ef2aSThomas Huth case 0x30:
1785fcf5ef2aSThomas Huth /* ZAP */
1786fcf5ef2aSThomas Huth if (islit) {
1787fcf5ef2aSThomas Huth gen_zapnoti(vc, va, ~lit);
1788fcf5ef2aSThomas Huth } else {
1789fcf5ef2aSThomas Huth gen_helper_zap(vc, va, load_gpr(ctx, rb));
1790fcf5ef2aSThomas Huth }
1791fcf5ef2aSThomas Huth break;
1792fcf5ef2aSThomas Huth case 0x31:
1793fcf5ef2aSThomas Huth /* ZAPNOT */
1794fcf5ef2aSThomas Huth if (islit) {
1795fcf5ef2aSThomas Huth gen_zapnoti(vc, va, lit);
1796fcf5ef2aSThomas Huth } else {
1797fcf5ef2aSThomas Huth gen_helper_zapnot(vc, va, load_gpr(ctx, rb));
1798fcf5ef2aSThomas Huth }
1799fcf5ef2aSThomas Huth break;
1800fcf5ef2aSThomas Huth case 0x32:
1801fcf5ef2aSThomas Huth /* MSKQL */
1802fcf5ef2aSThomas Huth gen_msk_l(ctx, vc, va, rb, islit, lit, 0xff);
1803fcf5ef2aSThomas Huth break;
1804fcf5ef2aSThomas Huth case 0x34:
1805fcf5ef2aSThomas Huth /* SRL */
1806fcf5ef2aSThomas Huth if (islit) {
1807fcf5ef2aSThomas Huth tcg_gen_shri_i64(vc, va, lit & 0x3f);
1808fcf5ef2aSThomas Huth } else {
1809fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1810fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
1811fcf5ef2aSThomas Huth tcg_gen_andi_i64(tmp, vb, 0x3f);
1812fcf5ef2aSThomas Huth tcg_gen_shr_i64(vc, va, tmp);
1813fcf5ef2aSThomas Huth }
1814fcf5ef2aSThomas Huth break;
1815fcf5ef2aSThomas Huth case 0x36:
1816fcf5ef2aSThomas Huth /* EXTQL */
1817fcf5ef2aSThomas Huth gen_ext_l(ctx, vc, va, rb, islit, lit, 0xff);
1818fcf5ef2aSThomas Huth break;
1819fcf5ef2aSThomas Huth case 0x39:
1820fcf5ef2aSThomas Huth /* SLL */
1821fcf5ef2aSThomas Huth if (islit) {
1822fcf5ef2aSThomas Huth tcg_gen_shli_i64(vc, va, lit & 0x3f);
1823fcf5ef2aSThomas Huth } else {
1824fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1825fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
1826fcf5ef2aSThomas Huth tcg_gen_andi_i64(tmp, vb, 0x3f);
1827fcf5ef2aSThomas Huth tcg_gen_shl_i64(vc, va, tmp);
1828fcf5ef2aSThomas Huth }
1829fcf5ef2aSThomas Huth break;
1830fcf5ef2aSThomas Huth case 0x3B:
1831fcf5ef2aSThomas Huth /* INSQL */
1832fcf5ef2aSThomas Huth gen_ins_l(ctx, vc, va, rb, islit, lit, 0xff);
1833fcf5ef2aSThomas Huth break;
1834fcf5ef2aSThomas Huth case 0x3C:
1835fcf5ef2aSThomas Huth /* SRA */
1836fcf5ef2aSThomas Huth if (islit) {
1837fcf5ef2aSThomas Huth tcg_gen_sari_i64(vc, va, lit & 0x3f);
1838fcf5ef2aSThomas Huth } else {
1839fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1840fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
1841fcf5ef2aSThomas Huth tcg_gen_andi_i64(tmp, vb, 0x3f);
1842fcf5ef2aSThomas Huth tcg_gen_sar_i64(vc, va, tmp);
1843fcf5ef2aSThomas Huth }
1844fcf5ef2aSThomas Huth break;
1845fcf5ef2aSThomas Huth case 0x52:
1846fcf5ef2aSThomas Huth /* MSKWH */
1847fcf5ef2aSThomas Huth gen_msk_h(ctx, vc, va, rb, islit, lit, 0x03);
1848fcf5ef2aSThomas Huth break;
1849fcf5ef2aSThomas Huth case 0x57:
1850fcf5ef2aSThomas Huth /* INSWH */
1851fcf5ef2aSThomas Huth gen_ins_h(ctx, vc, va, rb, islit, lit, 0x03);
1852fcf5ef2aSThomas Huth break;
1853fcf5ef2aSThomas Huth case 0x5A:
1854fcf5ef2aSThomas Huth /* EXTWH */
1855fcf5ef2aSThomas Huth gen_ext_h(ctx, vc, va, rb, islit, lit, 0x03);
1856fcf5ef2aSThomas Huth break;
1857fcf5ef2aSThomas Huth case 0x62:
1858fcf5ef2aSThomas Huth /* MSKLH */
1859fcf5ef2aSThomas Huth gen_msk_h(ctx, vc, va, rb, islit, lit, 0x0f);
1860fcf5ef2aSThomas Huth break;
1861fcf5ef2aSThomas Huth case 0x67:
1862fcf5ef2aSThomas Huth /* INSLH */
1863fcf5ef2aSThomas Huth gen_ins_h(ctx, vc, va, rb, islit, lit, 0x0f);
1864fcf5ef2aSThomas Huth break;
1865fcf5ef2aSThomas Huth case 0x6A:
1866fcf5ef2aSThomas Huth /* EXTLH */
1867fcf5ef2aSThomas Huth gen_ext_h(ctx, vc, va, rb, islit, lit, 0x0f);
1868fcf5ef2aSThomas Huth break;
1869fcf5ef2aSThomas Huth case 0x72:
1870fcf5ef2aSThomas Huth /* MSKQH */
1871fcf5ef2aSThomas Huth gen_msk_h(ctx, vc, va, rb, islit, lit, 0xff);
1872fcf5ef2aSThomas Huth break;
1873fcf5ef2aSThomas Huth case 0x77:
1874fcf5ef2aSThomas Huth /* INSQH */
1875fcf5ef2aSThomas Huth gen_ins_h(ctx, vc, va, rb, islit, lit, 0xff);
1876fcf5ef2aSThomas Huth break;
1877fcf5ef2aSThomas Huth case 0x7A:
1878fcf5ef2aSThomas Huth /* EXTQH */
1879fcf5ef2aSThomas Huth gen_ext_h(ctx, vc, va, rb, islit, lit, 0xff);
1880fcf5ef2aSThomas Huth break;
1881fcf5ef2aSThomas Huth default:
1882fcf5ef2aSThomas Huth goto invalid_opc;
1883fcf5ef2aSThomas Huth }
1884fcf5ef2aSThomas Huth break;
1885fcf5ef2aSThomas Huth
1886fcf5ef2aSThomas Huth case 0x13:
1887fcf5ef2aSThomas Huth vc = dest_gpr(ctx, rc);
1888fcf5ef2aSThomas Huth vb = load_gpr_lit(ctx, rb, lit, islit);
1889fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
1890fcf5ef2aSThomas Huth switch (fn7) {
1891fcf5ef2aSThomas Huth case 0x00:
1892fcf5ef2aSThomas Huth /* MULL */
1893fcf5ef2aSThomas Huth tcg_gen_mul_i64(vc, va, vb);
1894fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, vc);
1895fcf5ef2aSThomas Huth break;
1896fcf5ef2aSThomas Huth case 0x20:
1897fcf5ef2aSThomas Huth /* MULQ */
1898fcf5ef2aSThomas Huth tcg_gen_mul_i64(vc, va, vb);
1899fcf5ef2aSThomas Huth break;
1900fcf5ef2aSThomas Huth case 0x30:
1901fcf5ef2aSThomas Huth /* UMULH */
1902fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1903fcf5ef2aSThomas Huth tcg_gen_mulu2_i64(tmp, vc, va, vb);
1904fcf5ef2aSThomas Huth break;
1905fcf5ef2aSThomas Huth case 0x40:
1906fcf5ef2aSThomas Huth /* MULL/V */
1907fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1908fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(tmp, va);
1909fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, vb);
1910fcf5ef2aSThomas Huth tcg_gen_mul_i64(tmp, tmp, vc);
1911fcf5ef2aSThomas Huth tcg_gen_ext32s_i64(vc, tmp);
1912ad75a51eSRichard Henderson gen_helper_check_overflow(tcg_env, vc, tmp);
1913fcf5ef2aSThomas Huth break;
1914fcf5ef2aSThomas Huth case 0x60:
1915fcf5ef2aSThomas Huth /* MULQ/V */
1916fcf5ef2aSThomas Huth tmp = tcg_temp_new();
1917fcf5ef2aSThomas Huth tmp2 = tcg_temp_new();
1918fcf5ef2aSThomas Huth tcg_gen_muls2_i64(vc, tmp, va, vb);
1919fcf5ef2aSThomas Huth tcg_gen_sari_i64(tmp2, vc, 63);
1920ad75a51eSRichard Henderson gen_helper_check_overflow(tcg_env, tmp, tmp2);
1921fcf5ef2aSThomas Huth break;
1922fcf5ef2aSThomas Huth default:
1923fcf5ef2aSThomas Huth goto invalid_opc;
1924fcf5ef2aSThomas Huth }
1925fcf5ef2aSThomas Huth break;
1926fcf5ef2aSThomas Huth
1927fcf5ef2aSThomas Huth case 0x14:
1928c6d41b36SRichard Henderson REQUIRE_AMASK(FIX);
1929fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
1930fcf5ef2aSThomas Huth switch (fpfn) { /* fn11 & 0x3F */
1931fcf5ef2aSThomas Huth case 0x04:
1932fcf5ef2aSThomas Huth /* ITOFS */
1933fcf5ef2aSThomas Huth REQUIRE_REG_31(rb);
19349d14a042SRichard Henderson REQUIRE_FEN;
1935fcf5ef2aSThomas Huth t32 = tcg_temp_new_i32();
1936fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
1937fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(t32, va);
1938fcf5ef2aSThomas Huth gen_helper_memory_to_s(vc, t32);
1939fcf5ef2aSThomas Huth break;
1940fcf5ef2aSThomas Huth case 0x0A:
1941fcf5ef2aSThomas Huth /* SQRTF */
1942fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
19439d14a042SRichard Henderson REQUIRE_FEN;
1944fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
1945ad75a51eSRichard Henderson gen_helper_sqrtf(vc, tcg_env, vb);
1946fcf5ef2aSThomas Huth break;
1947fcf5ef2aSThomas Huth case 0x0B:
1948fcf5ef2aSThomas Huth /* SQRTS */
1949fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
19509d14a042SRichard Henderson REQUIRE_FEN;
1951fcf5ef2aSThomas Huth gen_sqrts(ctx, rb, rc, fn11);
1952fcf5ef2aSThomas Huth break;
1953fcf5ef2aSThomas Huth case 0x14:
1954fcf5ef2aSThomas Huth /* ITOFF */
1955fcf5ef2aSThomas Huth REQUIRE_REG_31(rb);
19569d14a042SRichard Henderson REQUIRE_FEN;
1957fcf5ef2aSThomas Huth t32 = tcg_temp_new_i32();
1958fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
1959fcf5ef2aSThomas Huth tcg_gen_extrl_i64_i32(t32, va);
1960fcf5ef2aSThomas Huth gen_helper_memory_to_f(vc, t32);
1961fcf5ef2aSThomas Huth break;
1962fcf5ef2aSThomas Huth case 0x24:
1963fcf5ef2aSThomas Huth /* ITOFT */
1964fcf5ef2aSThomas Huth REQUIRE_REG_31(rb);
19659d14a042SRichard Henderson REQUIRE_FEN;
1966fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
1967fcf5ef2aSThomas Huth tcg_gen_mov_i64(vc, va);
1968fcf5ef2aSThomas Huth break;
1969fcf5ef2aSThomas Huth case 0x2A:
1970fcf5ef2aSThomas Huth /* SQRTG */
1971fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
19729d14a042SRichard Henderson REQUIRE_FEN;
1973fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
1974ad75a51eSRichard Henderson gen_helper_sqrtg(vc, tcg_env, vb);
1975fcf5ef2aSThomas Huth break;
1976fcf5ef2aSThomas Huth case 0x02B:
1977fcf5ef2aSThomas Huth /* SQRTT */
1978fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
19799d14a042SRichard Henderson REQUIRE_FEN;
1980fcf5ef2aSThomas Huth gen_sqrtt(ctx, rb, rc, fn11);
1981fcf5ef2aSThomas Huth break;
1982fcf5ef2aSThomas Huth default:
1983fcf5ef2aSThomas Huth goto invalid_opc;
1984fcf5ef2aSThomas Huth }
1985fcf5ef2aSThomas Huth break;
1986fcf5ef2aSThomas Huth
1987fcf5ef2aSThomas Huth case 0x15:
1988fcf5ef2aSThomas Huth /* VAX floating point */
1989fcf5ef2aSThomas Huth /* XXX: rounding mode and trap are ignored (!) */
1990fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
1991fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
1992fcf5ef2aSThomas Huth va = load_fpr(ctx, ra);
1993fcf5ef2aSThomas Huth switch (fpfn) { /* fn11 & 0x3F */
1994fcf5ef2aSThomas Huth case 0x00:
1995fcf5ef2aSThomas Huth /* ADDF */
19969d14a042SRichard Henderson REQUIRE_FEN;
1997ad75a51eSRichard Henderson gen_helper_addf(vc, tcg_env, va, vb);
1998fcf5ef2aSThomas Huth break;
1999fcf5ef2aSThomas Huth case 0x01:
2000fcf5ef2aSThomas Huth /* SUBF */
20019d14a042SRichard Henderson REQUIRE_FEN;
2002ad75a51eSRichard Henderson gen_helper_subf(vc, tcg_env, va, vb);
2003fcf5ef2aSThomas Huth break;
2004fcf5ef2aSThomas Huth case 0x02:
2005fcf5ef2aSThomas Huth /* MULF */
20069d14a042SRichard Henderson REQUIRE_FEN;
2007ad75a51eSRichard Henderson gen_helper_mulf(vc, tcg_env, va, vb);
2008fcf5ef2aSThomas Huth break;
2009fcf5ef2aSThomas Huth case 0x03:
2010fcf5ef2aSThomas Huth /* DIVF */
20119d14a042SRichard Henderson REQUIRE_FEN;
2012ad75a51eSRichard Henderson gen_helper_divf(vc, tcg_env, va, vb);
2013fcf5ef2aSThomas Huth break;
2014fcf5ef2aSThomas Huth case 0x1E:
2015fcf5ef2aSThomas Huth /* CVTDG -- TODO */
2016fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2017fcf5ef2aSThomas Huth goto invalid_opc;
2018fcf5ef2aSThomas Huth case 0x20:
2019fcf5ef2aSThomas Huth /* ADDG */
20209d14a042SRichard Henderson REQUIRE_FEN;
2021ad75a51eSRichard Henderson gen_helper_addg(vc, tcg_env, va, vb);
2022fcf5ef2aSThomas Huth break;
2023fcf5ef2aSThomas Huth case 0x21:
2024fcf5ef2aSThomas Huth /* SUBG */
20259d14a042SRichard Henderson REQUIRE_FEN;
2026ad75a51eSRichard Henderson gen_helper_subg(vc, tcg_env, va, vb);
2027fcf5ef2aSThomas Huth break;
2028fcf5ef2aSThomas Huth case 0x22:
2029fcf5ef2aSThomas Huth /* MULG */
20309d14a042SRichard Henderson REQUIRE_FEN;
2031ad75a51eSRichard Henderson gen_helper_mulg(vc, tcg_env, va, vb);
2032fcf5ef2aSThomas Huth break;
2033fcf5ef2aSThomas Huth case 0x23:
2034fcf5ef2aSThomas Huth /* DIVG */
20359d14a042SRichard Henderson REQUIRE_FEN;
2036ad75a51eSRichard Henderson gen_helper_divg(vc, tcg_env, va, vb);
2037fcf5ef2aSThomas Huth break;
2038fcf5ef2aSThomas Huth case 0x25:
2039fcf5ef2aSThomas Huth /* CMPGEQ */
20409d14a042SRichard Henderson REQUIRE_FEN;
2041ad75a51eSRichard Henderson gen_helper_cmpgeq(vc, tcg_env, va, vb);
2042fcf5ef2aSThomas Huth break;
2043fcf5ef2aSThomas Huth case 0x26:
2044fcf5ef2aSThomas Huth /* CMPGLT */
20459d14a042SRichard Henderson REQUIRE_FEN;
2046ad75a51eSRichard Henderson gen_helper_cmpglt(vc, tcg_env, va, vb);
2047fcf5ef2aSThomas Huth break;
2048fcf5ef2aSThomas Huth case 0x27:
2049fcf5ef2aSThomas Huth /* CMPGLE */
20509d14a042SRichard Henderson REQUIRE_FEN;
2051ad75a51eSRichard Henderson gen_helper_cmpgle(vc, tcg_env, va, vb);
2052fcf5ef2aSThomas Huth break;
2053fcf5ef2aSThomas Huth case 0x2C:
2054fcf5ef2aSThomas Huth /* CVTGF */
2055fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
20569d14a042SRichard Henderson REQUIRE_FEN;
2057ad75a51eSRichard Henderson gen_helper_cvtgf(vc, tcg_env, vb);
2058fcf5ef2aSThomas Huth break;
2059fcf5ef2aSThomas Huth case 0x2D:
2060fcf5ef2aSThomas Huth /* CVTGD -- TODO */
2061fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2062fcf5ef2aSThomas Huth goto invalid_opc;
2063fcf5ef2aSThomas Huth case 0x2F:
2064fcf5ef2aSThomas Huth /* CVTGQ */
2065fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
20669d14a042SRichard Henderson REQUIRE_FEN;
2067ad75a51eSRichard Henderson gen_helper_cvtgq(vc, tcg_env, vb);
2068fcf5ef2aSThomas Huth break;
2069fcf5ef2aSThomas Huth case 0x3C:
2070fcf5ef2aSThomas Huth /* CVTQF */
2071fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
20729d14a042SRichard Henderson REQUIRE_FEN;
2073ad75a51eSRichard Henderson gen_helper_cvtqf(vc, tcg_env, vb);
2074fcf5ef2aSThomas Huth break;
2075fcf5ef2aSThomas Huth case 0x3E:
2076fcf5ef2aSThomas Huth /* CVTQG */
2077fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
20789d14a042SRichard Henderson REQUIRE_FEN;
2079ad75a51eSRichard Henderson gen_helper_cvtqg(vc, tcg_env, vb);
2080fcf5ef2aSThomas Huth break;
2081fcf5ef2aSThomas Huth default:
2082fcf5ef2aSThomas Huth goto invalid_opc;
2083fcf5ef2aSThomas Huth }
2084fcf5ef2aSThomas Huth break;
2085fcf5ef2aSThomas Huth
2086fcf5ef2aSThomas Huth case 0x16:
2087fcf5ef2aSThomas Huth /* IEEE floating-point */
2088fcf5ef2aSThomas Huth switch (fpfn) { /* fn11 & 0x3F */
2089fcf5ef2aSThomas Huth case 0x00:
2090fcf5ef2aSThomas Huth /* ADDS */
20919d14a042SRichard Henderson REQUIRE_FEN;
2092fcf5ef2aSThomas Huth gen_adds(ctx, ra, rb, rc, fn11);
2093fcf5ef2aSThomas Huth break;
2094fcf5ef2aSThomas Huth case 0x01:
2095fcf5ef2aSThomas Huth /* SUBS */
20969d14a042SRichard Henderson REQUIRE_FEN;
2097fcf5ef2aSThomas Huth gen_subs(ctx, ra, rb, rc, fn11);
2098fcf5ef2aSThomas Huth break;
2099fcf5ef2aSThomas Huth case 0x02:
2100fcf5ef2aSThomas Huth /* MULS */
21019d14a042SRichard Henderson REQUIRE_FEN;
2102fcf5ef2aSThomas Huth gen_muls(ctx, ra, rb, rc, fn11);
2103fcf5ef2aSThomas Huth break;
2104fcf5ef2aSThomas Huth case 0x03:
2105fcf5ef2aSThomas Huth /* DIVS */
21069d14a042SRichard Henderson REQUIRE_FEN;
2107fcf5ef2aSThomas Huth gen_divs(ctx, ra, rb, rc, fn11);
2108fcf5ef2aSThomas Huth break;
2109fcf5ef2aSThomas Huth case 0x20:
2110fcf5ef2aSThomas Huth /* ADDT */
21119d14a042SRichard Henderson REQUIRE_FEN;
2112fcf5ef2aSThomas Huth gen_addt(ctx, ra, rb, rc, fn11);
2113fcf5ef2aSThomas Huth break;
2114fcf5ef2aSThomas Huth case 0x21:
2115fcf5ef2aSThomas Huth /* SUBT */
21169d14a042SRichard Henderson REQUIRE_FEN;
2117fcf5ef2aSThomas Huth gen_subt(ctx, ra, rb, rc, fn11);
2118fcf5ef2aSThomas Huth break;
2119fcf5ef2aSThomas Huth case 0x22:
2120fcf5ef2aSThomas Huth /* MULT */
21219d14a042SRichard Henderson REQUIRE_FEN;
2122fcf5ef2aSThomas Huth gen_mult(ctx, ra, rb, rc, fn11);
2123fcf5ef2aSThomas Huth break;
2124fcf5ef2aSThomas Huth case 0x23:
2125fcf5ef2aSThomas Huth /* DIVT */
21269d14a042SRichard Henderson REQUIRE_FEN;
2127fcf5ef2aSThomas Huth gen_divt(ctx, ra, rb, rc, fn11);
2128fcf5ef2aSThomas Huth break;
2129fcf5ef2aSThomas Huth case 0x24:
2130fcf5ef2aSThomas Huth /* CMPTUN */
21319d14a042SRichard Henderson REQUIRE_FEN;
2132fcf5ef2aSThomas Huth gen_cmptun(ctx, ra, rb, rc, fn11);
2133fcf5ef2aSThomas Huth break;
2134fcf5ef2aSThomas Huth case 0x25:
2135fcf5ef2aSThomas Huth /* CMPTEQ */
21369d14a042SRichard Henderson REQUIRE_FEN;
2137fcf5ef2aSThomas Huth gen_cmpteq(ctx, ra, rb, rc, fn11);
2138fcf5ef2aSThomas Huth break;
2139fcf5ef2aSThomas Huth case 0x26:
2140fcf5ef2aSThomas Huth /* CMPTLT */
21419d14a042SRichard Henderson REQUIRE_FEN;
2142fcf5ef2aSThomas Huth gen_cmptlt(ctx, ra, rb, rc, fn11);
2143fcf5ef2aSThomas Huth break;
2144fcf5ef2aSThomas Huth case 0x27:
2145fcf5ef2aSThomas Huth /* CMPTLE */
21469d14a042SRichard Henderson REQUIRE_FEN;
2147fcf5ef2aSThomas Huth gen_cmptle(ctx, ra, rb, rc, fn11);
2148fcf5ef2aSThomas Huth break;
2149fcf5ef2aSThomas Huth case 0x2C:
2150fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
21519d14a042SRichard Henderson REQUIRE_FEN;
2152fcf5ef2aSThomas Huth if (fn11 == 0x2AC || fn11 == 0x6AC) {
2153fcf5ef2aSThomas Huth /* CVTST */
2154fcf5ef2aSThomas Huth gen_cvtst(ctx, rb, rc, fn11);
2155fcf5ef2aSThomas Huth } else {
2156fcf5ef2aSThomas Huth /* CVTTS */
2157fcf5ef2aSThomas Huth gen_cvtts(ctx, rb, rc, fn11);
2158fcf5ef2aSThomas Huth }
2159fcf5ef2aSThomas Huth break;
2160fcf5ef2aSThomas Huth case 0x2F:
2161fcf5ef2aSThomas Huth /* CVTTQ */
2162fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
21639d14a042SRichard Henderson REQUIRE_FEN;
2164fcf5ef2aSThomas Huth gen_cvttq(ctx, rb, rc, fn11);
2165fcf5ef2aSThomas Huth break;
2166fcf5ef2aSThomas Huth case 0x3C:
2167fcf5ef2aSThomas Huth /* CVTQS */
2168fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
21699d14a042SRichard Henderson REQUIRE_FEN;
2170fcf5ef2aSThomas Huth gen_cvtqs(ctx, rb, rc, fn11);
2171fcf5ef2aSThomas Huth break;
2172fcf5ef2aSThomas Huth case 0x3E:
2173fcf5ef2aSThomas Huth /* CVTQT */
2174fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
21759d14a042SRichard Henderson REQUIRE_FEN;
2176fcf5ef2aSThomas Huth gen_cvtqt(ctx, rb, rc, fn11);
2177fcf5ef2aSThomas Huth break;
2178fcf5ef2aSThomas Huth default:
2179fcf5ef2aSThomas Huth goto invalid_opc;
2180fcf5ef2aSThomas Huth }
2181fcf5ef2aSThomas Huth break;
2182fcf5ef2aSThomas Huth
2183fcf5ef2aSThomas Huth case 0x17:
2184fcf5ef2aSThomas Huth switch (fn11) {
2185fcf5ef2aSThomas Huth case 0x010:
2186fcf5ef2aSThomas Huth /* CVTLQ */
2187fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
21889d14a042SRichard Henderson REQUIRE_FEN;
2189fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
2190fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
2191fcf5ef2aSThomas Huth gen_cvtlq(vc, vb);
2192fcf5ef2aSThomas Huth break;
2193fcf5ef2aSThomas Huth case 0x020:
2194fcf5ef2aSThomas Huth /* CPYS */
21959d14a042SRichard Henderson REQUIRE_FEN;
2196fcf5ef2aSThomas Huth if (rc == 31) {
2197fcf5ef2aSThomas Huth /* Special case CPYS as FNOP. */
2198fcf5ef2aSThomas Huth } else {
2199fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
2200fcf5ef2aSThomas Huth va = load_fpr(ctx, ra);
2201fcf5ef2aSThomas Huth if (ra == rb) {
2202fcf5ef2aSThomas Huth /* Special case CPYS as FMOV. */
2203fcf5ef2aSThomas Huth tcg_gen_mov_i64(vc, va);
2204fcf5ef2aSThomas Huth } else {
2205fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
2206fcf5ef2aSThomas Huth gen_cpy_mask(vc, va, vb, 0, 0x8000000000000000ULL);
2207fcf5ef2aSThomas Huth }
2208fcf5ef2aSThomas Huth }
2209fcf5ef2aSThomas Huth break;
2210fcf5ef2aSThomas Huth case 0x021:
2211fcf5ef2aSThomas Huth /* CPYSN */
22129d14a042SRichard Henderson REQUIRE_FEN;
2213fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
2214fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
2215fcf5ef2aSThomas Huth va = load_fpr(ctx, ra);
2216fcf5ef2aSThomas Huth gen_cpy_mask(vc, va, vb, 1, 0x8000000000000000ULL);
2217fcf5ef2aSThomas Huth break;
2218fcf5ef2aSThomas Huth case 0x022:
2219fcf5ef2aSThomas Huth /* CPYSE */
22209d14a042SRichard Henderson REQUIRE_FEN;
2221fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
2222fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
2223fcf5ef2aSThomas Huth va = load_fpr(ctx, ra);
2224fcf5ef2aSThomas Huth gen_cpy_mask(vc, va, vb, 0, 0xFFF0000000000000ULL);
2225fcf5ef2aSThomas Huth break;
2226fcf5ef2aSThomas Huth case 0x024:
2227fcf5ef2aSThomas Huth /* MT_FPCR */
22289d14a042SRichard Henderson REQUIRE_FEN;
2229fcf5ef2aSThomas Huth va = load_fpr(ctx, ra);
2230ad75a51eSRichard Henderson gen_helper_store_fpcr(tcg_env, va);
2231fcf5ef2aSThomas Huth if (ctx->tb_rm == QUAL_RM_D) {
2232fcf5ef2aSThomas Huth /* Re-do the copy of the rounding mode to fp_status
2233fcf5ef2aSThomas Huth the next time we use dynamic rounding. */
2234fcf5ef2aSThomas Huth ctx->tb_rm = -1;
2235fcf5ef2aSThomas Huth }
2236fcf5ef2aSThomas Huth break;
2237fcf5ef2aSThomas Huth case 0x025:
2238fcf5ef2aSThomas Huth /* MF_FPCR */
22399d14a042SRichard Henderson REQUIRE_FEN;
2240fcf5ef2aSThomas Huth va = dest_fpr(ctx, ra);
2241ad75a51eSRichard Henderson gen_helper_load_fpcr(va, tcg_env);
2242fcf5ef2aSThomas Huth break;
2243fcf5ef2aSThomas Huth case 0x02A:
2244fcf5ef2aSThomas Huth /* FCMOVEQ */
22459d14a042SRichard Henderson REQUIRE_FEN;
2246fcf5ef2aSThomas Huth gen_fcmov(ctx, TCG_COND_EQ, ra, rb, rc);
2247fcf5ef2aSThomas Huth break;
2248fcf5ef2aSThomas Huth case 0x02B:
2249fcf5ef2aSThomas Huth /* FCMOVNE */
22509d14a042SRichard Henderson REQUIRE_FEN;
2251fcf5ef2aSThomas Huth gen_fcmov(ctx, TCG_COND_NE, ra, rb, rc);
2252fcf5ef2aSThomas Huth break;
2253fcf5ef2aSThomas Huth case 0x02C:
2254fcf5ef2aSThomas Huth /* FCMOVLT */
22559d14a042SRichard Henderson REQUIRE_FEN;
2256fcf5ef2aSThomas Huth gen_fcmov(ctx, TCG_COND_LT, ra, rb, rc);
2257fcf5ef2aSThomas Huth break;
2258fcf5ef2aSThomas Huth case 0x02D:
2259fcf5ef2aSThomas Huth /* FCMOVGE */
22609d14a042SRichard Henderson REQUIRE_FEN;
2261fcf5ef2aSThomas Huth gen_fcmov(ctx, TCG_COND_GE, ra, rb, rc);
2262fcf5ef2aSThomas Huth break;
2263fcf5ef2aSThomas Huth case 0x02E:
2264fcf5ef2aSThomas Huth /* FCMOVLE */
22659d14a042SRichard Henderson REQUIRE_FEN;
2266fcf5ef2aSThomas Huth gen_fcmov(ctx, TCG_COND_LE, ra, rb, rc);
2267fcf5ef2aSThomas Huth break;
2268fcf5ef2aSThomas Huth case 0x02F:
2269fcf5ef2aSThomas Huth /* FCMOVGT */
22709d14a042SRichard Henderson REQUIRE_FEN;
2271fcf5ef2aSThomas Huth gen_fcmov(ctx, TCG_COND_GT, ra, rb, rc);
2272fcf5ef2aSThomas Huth break;
2273fcf5ef2aSThomas Huth case 0x030: /* CVTQL */
2274fcf5ef2aSThomas Huth case 0x130: /* CVTQL/V */
2275fcf5ef2aSThomas Huth case 0x530: /* CVTQL/SV */
2276fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
22779d14a042SRichard Henderson REQUIRE_FEN;
2278fcf5ef2aSThomas Huth vc = dest_fpr(ctx, rc);
2279fcf5ef2aSThomas Huth vb = load_fpr(ctx, rb);
2280ad75a51eSRichard Henderson gen_helper_cvtql(vc, tcg_env, vb);
2281fcf5ef2aSThomas Huth gen_fp_exc_raise(rc, fn11);
2282fcf5ef2aSThomas Huth break;
2283fcf5ef2aSThomas Huth default:
2284fcf5ef2aSThomas Huth goto invalid_opc;
2285fcf5ef2aSThomas Huth }
2286fcf5ef2aSThomas Huth break;
2287fcf5ef2aSThomas Huth
2288fcf5ef2aSThomas Huth case 0x18:
2289fcf5ef2aSThomas Huth switch ((uint16_t)disp16) {
2290fcf5ef2aSThomas Huth case 0x0000:
2291fcf5ef2aSThomas Huth /* TRAPB */
2292fcf5ef2aSThomas Huth /* No-op. */
2293fcf5ef2aSThomas Huth break;
2294fcf5ef2aSThomas Huth case 0x0400:
2295fcf5ef2aSThomas Huth /* EXCB */
2296fcf5ef2aSThomas Huth /* No-op. */
2297fcf5ef2aSThomas Huth break;
2298fcf5ef2aSThomas Huth case 0x4000:
2299fcf5ef2aSThomas Huth /* MB */
2300fcf5ef2aSThomas Huth tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
2301fcf5ef2aSThomas Huth break;
2302fcf5ef2aSThomas Huth case 0x4400:
2303fcf5ef2aSThomas Huth /* WMB */
2304fcf5ef2aSThomas Huth tcg_gen_mb(TCG_MO_ST_ST | TCG_BAR_SC);
2305fcf5ef2aSThomas Huth break;
2306fcf5ef2aSThomas Huth case 0x8000:
2307fcf5ef2aSThomas Huth /* FETCH */
2308fcf5ef2aSThomas Huth /* No-op */
2309fcf5ef2aSThomas Huth break;
2310fcf5ef2aSThomas Huth case 0xA000:
2311fcf5ef2aSThomas Huth /* FETCH_M */
2312fcf5ef2aSThomas Huth /* No-op */
2313fcf5ef2aSThomas Huth break;
2314fcf5ef2aSThomas Huth case 0xC000:
2315fcf5ef2aSThomas Huth /* RPCC */
2316fcf5ef2aSThomas Huth va = dest_gpr(ctx, ra);
2317dfd1b812SRichard Henderson if (translator_io_start(&ctx->base)) {
23183de811c6SRichard Henderson ret = DISAS_PC_STALE;
2319fcf5ef2aSThomas Huth }
2320ad75a51eSRichard Henderson gen_helper_load_pcc(va, tcg_env);
2321fcf5ef2aSThomas Huth break;
2322fcf5ef2aSThomas Huth case 0xE000:
2323fcf5ef2aSThomas Huth /* RC */
2324fcf5ef2aSThomas Huth gen_rx(ctx, ra, 0);
2325fcf5ef2aSThomas Huth break;
2326fcf5ef2aSThomas Huth case 0xE800:
2327fcf5ef2aSThomas Huth /* ECB */
2328fcf5ef2aSThomas Huth break;
2329fcf5ef2aSThomas Huth case 0xF000:
2330fcf5ef2aSThomas Huth /* RS */
2331fcf5ef2aSThomas Huth gen_rx(ctx, ra, 1);
2332fcf5ef2aSThomas Huth break;
2333fcf5ef2aSThomas Huth case 0xF800:
2334fcf5ef2aSThomas Huth /* WH64 */
2335fcf5ef2aSThomas Huth /* No-op */
2336fcf5ef2aSThomas Huth break;
2337fcf5ef2aSThomas Huth case 0xFC00:
2338fcf5ef2aSThomas Huth /* WH64EN */
2339fcf5ef2aSThomas Huth /* No-op */
2340fcf5ef2aSThomas Huth break;
2341fcf5ef2aSThomas Huth default:
2342fcf5ef2aSThomas Huth goto invalid_opc;
2343fcf5ef2aSThomas Huth }
2344fcf5ef2aSThomas Huth break;
2345fcf5ef2aSThomas Huth
2346fcf5ef2aSThomas Huth case 0x19:
2347fcf5ef2aSThomas Huth /* HW_MFPR (PALcode) */
2348fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
2349bcd2625dSRichard Henderson REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2350fcf5ef2aSThomas Huth va = dest_gpr(ctx, ra);
2351fcf5ef2aSThomas Huth ret = gen_mfpr(ctx, va, insn & 0xffff);
2352fcf5ef2aSThomas Huth break;
2353fcf5ef2aSThomas Huth #else
2354fcf5ef2aSThomas Huth goto invalid_opc;
2355fcf5ef2aSThomas Huth #endif
2356fcf5ef2aSThomas Huth
2357fcf5ef2aSThomas Huth case 0x1A:
2358fcf5ef2aSThomas Huth /* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
2359fcf5ef2aSThomas Huth prediction stack action, which of course we don't implement. */
2360fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
2361fcf5ef2aSThomas Huth if (ra != 31) {
2362b1a3eacfSRichard Henderson tmp = tcg_temp_new();
2363b1a3eacfSRichard Henderson tcg_gen_andi_i64(tmp, vb, ~3);
2364b1a3eacfSRichard Henderson gen_pc_disp(ctx, ctx->ir[ra], 0);
2365b1a3eacfSRichard Henderson tcg_gen_mov_i64(cpu_pc, tmp);
2366b1a3eacfSRichard Henderson } else {
2367b1a3eacfSRichard Henderson tcg_gen_andi_i64(cpu_pc, vb, ~3);
2368fcf5ef2aSThomas Huth }
23693de811c6SRichard Henderson ret = DISAS_PC_UPDATED;
2370fcf5ef2aSThomas Huth break;
2371fcf5ef2aSThomas Huth
2372fcf5ef2aSThomas Huth case 0x1B:
2373fcf5ef2aSThomas Huth /* HW_LD (PALcode) */
2374fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
2375bcd2625dSRichard Henderson REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2376fcf5ef2aSThomas Huth {
2377fcf5ef2aSThomas Huth TCGv addr = tcg_temp_new();
2378fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
2379fcf5ef2aSThomas Huth va = dest_gpr(ctx, ra);
2380fcf5ef2aSThomas Huth
2381fcf5ef2aSThomas Huth tcg_gen_addi_i64(addr, vb, disp12);
2382fcf5ef2aSThomas Huth switch ((insn >> 12) & 0xF) {
2383fcf5ef2aSThomas Huth case 0x0:
2384fcf5ef2aSThomas Huth /* Longword physical access (hw_ldl/p) */
238533948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
2386fcf5ef2aSThomas Huth break;
2387fcf5ef2aSThomas Huth case 0x1:
2388fcf5ef2aSThomas Huth /* Quadword physical access (hw_ldq/p) */
238933948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
2390fcf5ef2aSThomas Huth break;
2391fcf5ef2aSThomas Huth case 0x2:
2392fcf5ef2aSThomas Huth /* Longword physical access with lock (hw_ldl_l/p) */
239333948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
23945ffcb334SRichard Henderson tcg_gen_mov_i64(cpu_lock_addr, addr);
23955ffcb334SRichard Henderson tcg_gen_mov_i64(cpu_lock_value, va);
2396fcf5ef2aSThomas Huth break;
2397fcf5ef2aSThomas Huth case 0x3:
2398fcf5ef2aSThomas Huth /* Quadword physical access with lock (hw_ldq_l/p) */
239933948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
24005ffcb334SRichard Henderson tcg_gen_mov_i64(cpu_lock_addr, addr);
24015ffcb334SRichard Henderson tcg_gen_mov_i64(cpu_lock_value, va);
2402fcf5ef2aSThomas Huth break;
2403fcf5ef2aSThomas Huth case 0x4:
2404fcf5ef2aSThomas Huth /* Longword virtual PTE fetch (hw_ldl/v) */
2405fcf5ef2aSThomas Huth goto invalid_opc;
2406fcf5ef2aSThomas Huth case 0x5:
2407fcf5ef2aSThomas Huth /* Quadword virtual PTE fetch (hw_ldq/v) */
2408fcf5ef2aSThomas Huth goto invalid_opc;
2409fcf5ef2aSThomas Huth break;
2410fcf5ef2aSThomas Huth case 0x6:
2411fcf5ef2aSThomas Huth /* Invalid */
2412fcf5ef2aSThomas Huth goto invalid_opc;
2413fcf5ef2aSThomas Huth case 0x7:
2414fcf5ef2aSThomas Huth /* Invaliid */
2415fcf5ef2aSThomas Huth goto invalid_opc;
2416fcf5ef2aSThomas Huth case 0x8:
2417fcf5ef2aSThomas Huth /* Longword virtual access (hw_ldl) */
2418fcf5ef2aSThomas Huth goto invalid_opc;
2419fcf5ef2aSThomas Huth case 0x9:
2420fcf5ef2aSThomas Huth /* Quadword virtual access (hw_ldq) */
2421fcf5ef2aSThomas Huth goto invalid_opc;
2422fcf5ef2aSThomas Huth case 0xA:
2423fcf5ef2aSThomas Huth /* Longword virtual access with protection check (hw_ldl/w) */
242433948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
242533948b68SRichard Henderson MO_LESL | MO_ALIGN);
2426fcf5ef2aSThomas Huth break;
2427fcf5ef2aSThomas Huth case 0xB:
2428fcf5ef2aSThomas Huth /* Quadword virtual access with protection check (hw_ldq/w) */
242933948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_KERNEL_IDX,
243033948b68SRichard Henderson MO_LEUQ | MO_ALIGN);
2431fcf5ef2aSThomas Huth break;
2432fcf5ef2aSThomas Huth case 0xC:
2433fcf5ef2aSThomas Huth /* Longword virtual access with alt access mode (hw_ldl/a)*/
2434fcf5ef2aSThomas Huth goto invalid_opc;
2435fcf5ef2aSThomas Huth case 0xD:
2436fcf5ef2aSThomas Huth /* Quadword virtual access with alt access mode (hw_ldq/a) */
2437fcf5ef2aSThomas Huth goto invalid_opc;
2438fcf5ef2aSThomas Huth case 0xE:
2439fcf5ef2aSThomas Huth /* Longword virtual access with alternate access mode and
2440fcf5ef2aSThomas Huth protection checks (hw_ldl/wa) */
244133948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
244233948b68SRichard Henderson MO_LESL | MO_ALIGN);
2443fcf5ef2aSThomas Huth break;
2444fcf5ef2aSThomas Huth case 0xF:
2445fcf5ef2aSThomas Huth /* Quadword virtual access with alternate access mode and
2446fcf5ef2aSThomas Huth protection checks (hw_ldq/wa) */
244733948b68SRichard Henderson tcg_gen_qemu_ld_i64(va, addr, MMU_USER_IDX,
244833948b68SRichard Henderson MO_LEUQ | MO_ALIGN);
2449fcf5ef2aSThomas Huth break;
2450fcf5ef2aSThomas Huth }
2451fcf5ef2aSThomas Huth break;
2452fcf5ef2aSThomas Huth }
2453fcf5ef2aSThomas Huth #else
2454fcf5ef2aSThomas Huth goto invalid_opc;
2455fcf5ef2aSThomas Huth #endif
2456fcf5ef2aSThomas Huth
2457fcf5ef2aSThomas Huth case 0x1C:
2458fcf5ef2aSThomas Huth vc = dest_gpr(ctx, rc);
2459fcf5ef2aSThomas Huth if (fn7 == 0x70) {
2460fcf5ef2aSThomas Huth /* FTOIT */
2461c6d41b36SRichard Henderson REQUIRE_AMASK(FIX);
2462fcf5ef2aSThomas Huth REQUIRE_REG_31(rb);
2463fcf5ef2aSThomas Huth va = load_fpr(ctx, ra);
2464fcf5ef2aSThomas Huth tcg_gen_mov_i64(vc, va);
2465fcf5ef2aSThomas Huth break;
2466fcf5ef2aSThomas Huth } else if (fn7 == 0x78) {
2467fcf5ef2aSThomas Huth /* FTOIS */
2468c6d41b36SRichard Henderson REQUIRE_AMASK(FIX);
2469fcf5ef2aSThomas Huth REQUIRE_REG_31(rb);
2470fcf5ef2aSThomas Huth t32 = tcg_temp_new_i32();
2471fcf5ef2aSThomas Huth va = load_fpr(ctx, ra);
2472fcf5ef2aSThomas Huth gen_helper_s_to_memory(t32, va);
2473fcf5ef2aSThomas Huth tcg_gen_ext_i32_i64(vc, t32);
2474fcf5ef2aSThomas Huth break;
2475fcf5ef2aSThomas Huth }
2476fcf5ef2aSThomas Huth
2477fcf5ef2aSThomas Huth vb = load_gpr_lit(ctx, rb, lit, islit);
2478fcf5ef2aSThomas Huth switch (fn7) {
2479fcf5ef2aSThomas Huth case 0x00:
2480fcf5ef2aSThomas Huth /* SEXTB */
2481c6d41b36SRichard Henderson REQUIRE_AMASK(BWX);
2482fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2483fcf5ef2aSThomas Huth tcg_gen_ext8s_i64(vc, vb);
2484fcf5ef2aSThomas Huth break;
2485fcf5ef2aSThomas Huth case 0x01:
2486fcf5ef2aSThomas Huth /* SEXTW */
2487c6d41b36SRichard Henderson REQUIRE_AMASK(BWX);
2488fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2489fcf5ef2aSThomas Huth tcg_gen_ext16s_i64(vc, vb);
2490fcf5ef2aSThomas Huth break;
2491fcf5ef2aSThomas Huth case 0x30:
2492fcf5ef2aSThomas Huth /* CTPOP */
2493c6d41b36SRichard Henderson REQUIRE_AMASK(CIX);
2494fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2495fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2496de26a584SRichard Henderson tcg_gen_ctpop_i64(vc, vb);
2497fcf5ef2aSThomas Huth break;
2498fcf5ef2aSThomas Huth case 0x31:
2499fcf5ef2aSThomas Huth /* PERR */
2500c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2501fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2502fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2503fcf5ef2aSThomas Huth gen_helper_perr(vc, va, vb);
2504fcf5ef2aSThomas Huth break;
2505fcf5ef2aSThomas Huth case 0x32:
2506fcf5ef2aSThomas Huth /* CTLZ */
2507c6d41b36SRichard Henderson REQUIRE_AMASK(CIX);
2508fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2509fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2510881549daSRichard Henderson tcg_gen_clzi_i64(vc, vb, 64);
2511fcf5ef2aSThomas Huth break;
2512fcf5ef2aSThomas Huth case 0x33:
2513fcf5ef2aSThomas Huth /* CTTZ */
2514c6d41b36SRichard Henderson REQUIRE_AMASK(CIX);
2515fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2516fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2517881549daSRichard Henderson tcg_gen_ctzi_i64(vc, vb, 64);
2518fcf5ef2aSThomas Huth break;
2519fcf5ef2aSThomas Huth case 0x34:
2520fcf5ef2aSThomas Huth /* UNPKBW */
2521c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2522fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2523fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2524fcf5ef2aSThomas Huth gen_helper_unpkbw(vc, vb);
2525fcf5ef2aSThomas Huth break;
2526fcf5ef2aSThomas Huth case 0x35:
2527fcf5ef2aSThomas Huth /* UNPKBL */
2528c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2529fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2530fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2531fcf5ef2aSThomas Huth gen_helper_unpkbl(vc, vb);
2532fcf5ef2aSThomas Huth break;
2533fcf5ef2aSThomas Huth case 0x36:
2534fcf5ef2aSThomas Huth /* PKWB */
2535c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2536fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2537fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2538fcf5ef2aSThomas Huth gen_helper_pkwb(vc, vb);
2539fcf5ef2aSThomas Huth break;
2540fcf5ef2aSThomas Huth case 0x37:
2541fcf5ef2aSThomas Huth /* PKLB */
2542c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2543fcf5ef2aSThomas Huth REQUIRE_REG_31(ra);
2544fcf5ef2aSThomas Huth REQUIRE_NO_LIT;
2545fcf5ef2aSThomas Huth gen_helper_pklb(vc, vb);
2546fcf5ef2aSThomas Huth break;
2547fcf5ef2aSThomas Huth case 0x38:
2548fcf5ef2aSThomas Huth /* MINSB8 */
2549c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2550fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2551fcf5ef2aSThomas Huth gen_helper_minsb8(vc, va, vb);
2552fcf5ef2aSThomas Huth break;
2553fcf5ef2aSThomas Huth case 0x39:
2554fcf5ef2aSThomas Huth /* MINSW4 */
2555c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2556fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2557fcf5ef2aSThomas Huth gen_helper_minsw4(vc, va, vb);
2558fcf5ef2aSThomas Huth break;
2559fcf5ef2aSThomas Huth case 0x3A:
2560fcf5ef2aSThomas Huth /* MINUB8 */
2561c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2562fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2563fcf5ef2aSThomas Huth gen_helper_minub8(vc, va, vb);
2564fcf5ef2aSThomas Huth break;
2565fcf5ef2aSThomas Huth case 0x3B:
2566fcf5ef2aSThomas Huth /* MINUW4 */
2567c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2568fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2569fcf5ef2aSThomas Huth gen_helper_minuw4(vc, va, vb);
2570fcf5ef2aSThomas Huth break;
2571fcf5ef2aSThomas Huth case 0x3C:
2572fcf5ef2aSThomas Huth /* MAXUB8 */
2573c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2574fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2575fcf5ef2aSThomas Huth gen_helper_maxub8(vc, va, vb);
2576fcf5ef2aSThomas Huth break;
2577fcf5ef2aSThomas Huth case 0x3D:
2578fcf5ef2aSThomas Huth /* MAXUW4 */
2579c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2580fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2581fcf5ef2aSThomas Huth gen_helper_maxuw4(vc, va, vb);
2582fcf5ef2aSThomas Huth break;
2583fcf5ef2aSThomas Huth case 0x3E:
2584fcf5ef2aSThomas Huth /* MAXSB8 */
2585c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2586fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2587fcf5ef2aSThomas Huth gen_helper_maxsb8(vc, va, vb);
2588fcf5ef2aSThomas Huth break;
2589fcf5ef2aSThomas Huth case 0x3F:
2590fcf5ef2aSThomas Huth /* MAXSW4 */
2591c6d41b36SRichard Henderson REQUIRE_AMASK(MVI);
2592fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2593fcf5ef2aSThomas Huth gen_helper_maxsw4(vc, va, vb);
2594fcf5ef2aSThomas Huth break;
2595fcf5ef2aSThomas Huth default:
2596fcf5ef2aSThomas Huth goto invalid_opc;
2597fcf5ef2aSThomas Huth }
2598fcf5ef2aSThomas Huth break;
2599fcf5ef2aSThomas Huth
2600fcf5ef2aSThomas Huth case 0x1D:
2601fcf5ef2aSThomas Huth /* HW_MTPR (PALcode) */
2602fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
2603bcd2625dSRichard Henderson REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2604fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
2605fcf5ef2aSThomas Huth ret = gen_mtpr(ctx, vb, insn & 0xffff);
2606fcf5ef2aSThomas Huth break;
2607fcf5ef2aSThomas Huth #else
2608fcf5ef2aSThomas Huth goto invalid_opc;
2609fcf5ef2aSThomas Huth #endif
2610fcf5ef2aSThomas Huth
2611fcf5ef2aSThomas Huth case 0x1E:
2612fcf5ef2aSThomas Huth /* HW_RET (PALcode) */
2613fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
2614bcd2625dSRichard Henderson REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2615fcf5ef2aSThomas Huth if (rb == 31) {
2616fcf5ef2aSThomas Huth /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
2617fcf5ef2aSThomas Huth address from EXC_ADDR. This turns out to be useful for our
2618fcf5ef2aSThomas Huth emulation PALcode, so continue to accept it. */
26193e646c3aSRichard Henderson vb = dest_sink(ctx);
2620ad75a51eSRichard Henderson tcg_gen_ld_i64(vb, tcg_env, offsetof(CPUAlphaState, exc_addr));
2621fcf5ef2aSThomas Huth } else {
2622fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
2623fcf5ef2aSThomas Huth }
2624bcd2625dSRichard Henderson tcg_gen_movi_i64(cpu_lock_addr, -1);
2625904bd855SRichard Henderson st_flag_byte(load_zero(ctx), ENV_FLAG_RX_SHIFT);
2626fcf5ef2aSThomas Huth tmp = tcg_temp_new();
2627fcf5ef2aSThomas Huth tcg_gen_andi_i64(tmp, vb, 1);
2628bcd2625dSRichard Henderson st_flag_byte(tmp, ENV_FLAG_PAL_SHIFT);
2629fcf5ef2aSThomas Huth tcg_gen_andi_i64(cpu_pc, vb, ~3);
263054e1d4edSRichard Henderson /* Allow interrupts to be recognized right away. */
26313de811c6SRichard Henderson ret = DISAS_PC_UPDATED_NOCHAIN;
2632fcf5ef2aSThomas Huth break;
2633fcf5ef2aSThomas Huth #else
2634fcf5ef2aSThomas Huth goto invalid_opc;
2635fcf5ef2aSThomas Huth #endif
2636fcf5ef2aSThomas Huth
2637fcf5ef2aSThomas Huth case 0x1F:
2638fcf5ef2aSThomas Huth /* HW_ST (PALcode) */
2639fcf5ef2aSThomas Huth #ifndef CONFIG_USER_ONLY
2640bcd2625dSRichard Henderson REQUIRE_TB_FLAG(ENV_FLAG_PAL_MODE);
2641fcf5ef2aSThomas Huth {
2642fcf5ef2aSThomas Huth switch ((insn >> 12) & 0xF) {
2643fcf5ef2aSThomas Huth case 0x0:
2644fcf5ef2aSThomas Huth /* Longword physical access */
2645fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2646fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
2647fcf5ef2aSThomas Huth tmp = tcg_temp_new();
2648fcf5ef2aSThomas Huth tcg_gen_addi_i64(tmp, vb, disp12);
264933948b68SRichard Henderson tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
2650fcf5ef2aSThomas Huth break;
2651fcf5ef2aSThomas Huth case 0x1:
2652fcf5ef2aSThomas Huth /* Quadword physical access */
2653fcf5ef2aSThomas Huth va = load_gpr(ctx, ra);
2654fcf5ef2aSThomas Huth vb = load_gpr(ctx, rb);
2655fcf5ef2aSThomas Huth tmp = tcg_temp_new();
2656fcf5ef2aSThomas Huth tcg_gen_addi_i64(tmp, vb, disp12);
265733948b68SRichard Henderson tcg_gen_qemu_st_i64(va, tmp, MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
2658fcf5ef2aSThomas Huth break;
2659fcf5ef2aSThomas Huth case 0x2:
2660fcf5ef2aSThomas Huth /* Longword physical access with lock */
2661fcf5ef2aSThomas Huth ret = gen_store_conditional(ctx, ra, rb, disp12,
266233948b68SRichard Henderson MMU_PHYS_IDX, MO_LESL | MO_ALIGN);
2663fcf5ef2aSThomas Huth break;
2664fcf5ef2aSThomas Huth case 0x3:
2665fcf5ef2aSThomas Huth /* Quadword physical access with lock */
2666fcf5ef2aSThomas Huth ret = gen_store_conditional(ctx, ra, rb, disp12,
266733948b68SRichard Henderson MMU_PHYS_IDX, MO_LEUQ | MO_ALIGN);
2668fcf5ef2aSThomas Huth break;
2669fcf5ef2aSThomas Huth case 0x4:
2670fcf5ef2aSThomas Huth /* Longword virtual access */
2671fcf5ef2aSThomas Huth goto invalid_opc;
2672fcf5ef2aSThomas Huth case 0x5:
2673fcf5ef2aSThomas Huth /* Quadword virtual access */
2674fcf5ef2aSThomas Huth goto invalid_opc;
2675fcf5ef2aSThomas Huth case 0x6:
2676fcf5ef2aSThomas Huth /* Invalid */
2677fcf5ef2aSThomas Huth goto invalid_opc;
2678fcf5ef2aSThomas Huth case 0x7:
2679fcf5ef2aSThomas Huth /* Invalid */
2680fcf5ef2aSThomas Huth goto invalid_opc;
2681fcf5ef2aSThomas Huth case 0x8:
2682fcf5ef2aSThomas Huth /* Invalid */
2683fcf5ef2aSThomas Huth goto invalid_opc;
2684fcf5ef2aSThomas Huth case 0x9:
2685fcf5ef2aSThomas Huth /* Invalid */
2686fcf5ef2aSThomas Huth goto invalid_opc;
2687fcf5ef2aSThomas Huth case 0xA:
2688fcf5ef2aSThomas Huth /* Invalid */
2689fcf5ef2aSThomas Huth goto invalid_opc;
2690fcf5ef2aSThomas Huth case 0xB:
2691fcf5ef2aSThomas Huth /* Invalid */
2692fcf5ef2aSThomas Huth goto invalid_opc;
2693fcf5ef2aSThomas Huth case 0xC:
2694fcf5ef2aSThomas Huth /* Longword virtual access with alternate access mode */
2695fcf5ef2aSThomas Huth goto invalid_opc;
2696fcf5ef2aSThomas Huth case 0xD:
2697fcf5ef2aSThomas Huth /* Quadword virtual access with alternate access mode */
2698fcf5ef2aSThomas Huth goto invalid_opc;
2699fcf5ef2aSThomas Huth case 0xE:
2700fcf5ef2aSThomas Huth /* Invalid */
2701fcf5ef2aSThomas Huth goto invalid_opc;
2702fcf5ef2aSThomas Huth case 0xF:
2703fcf5ef2aSThomas Huth /* Invalid */
2704fcf5ef2aSThomas Huth goto invalid_opc;
2705fcf5ef2aSThomas Huth }
2706fcf5ef2aSThomas Huth break;
2707fcf5ef2aSThomas Huth }
2708fcf5ef2aSThomas Huth #else
2709fcf5ef2aSThomas Huth goto invalid_opc;
2710fcf5ef2aSThomas Huth #endif
2711fcf5ef2aSThomas Huth case 0x20:
2712fcf5ef2aSThomas Huth /* LDF */
27139d14a042SRichard Henderson REQUIRE_FEN;
271445263531SRichard Henderson gen_load_fp(ctx, ra, rb, disp16, gen_ldf);
2715fcf5ef2aSThomas Huth break;
2716fcf5ef2aSThomas Huth case 0x21:
2717fcf5ef2aSThomas Huth /* LDG */
27189d14a042SRichard Henderson REQUIRE_FEN;
271945263531SRichard Henderson gen_load_fp(ctx, ra, rb, disp16, gen_ldg);
2720fcf5ef2aSThomas Huth break;
2721fcf5ef2aSThomas Huth case 0x22:
2722fcf5ef2aSThomas Huth /* LDS */
27239d14a042SRichard Henderson REQUIRE_FEN;
272445263531SRichard Henderson gen_load_fp(ctx, ra, rb, disp16, gen_lds);
2725fcf5ef2aSThomas Huth break;
2726fcf5ef2aSThomas Huth case 0x23:
2727fcf5ef2aSThomas Huth /* LDT */
27289d14a042SRichard Henderson REQUIRE_FEN;
272945263531SRichard Henderson gen_load_fp(ctx, ra, rb, disp16, gen_ldt);
2730fcf5ef2aSThomas Huth break;
2731fcf5ef2aSThomas Huth case 0x24:
2732fcf5ef2aSThomas Huth /* STF */
27339d14a042SRichard Henderson REQUIRE_FEN;
273445263531SRichard Henderson gen_store_fp(ctx, ra, rb, disp16, gen_stf);
2735fcf5ef2aSThomas Huth break;
2736fcf5ef2aSThomas Huth case 0x25:
2737fcf5ef2aSThomas Huth /* STG */
27389d14a042SRichard Henderson REQUIRE_FEN;
273945263531SRichard Henderson gen_store_fp(ctx, ra, rb, disp16, gen_stg);
2740fcf5ef2aSThomas Huth break;
2741fcf5ef2aSThomas Huth case 0x26:
2742fcf5ef2aSThomas Huth /* STS */
27439d14a042SRichard Henderson REQUIRE_FEN;
274445263531SRichard Henderson gen_store_fp(ctx, ra, rb, disp16, gen_sts);
2745fcf5ef2aSThomas Huth break;
2746fcf5ef2aSThomas Huth case 0x27:
2747fcf5ef2aSThomas Huth /* STT */
27489d14a042SRichard Henderson REQUIRE_FEN;
274945263531SRichard Henderson gen_store_fp(ctx, ra, rb, disp16, gen_stt);
2750fcf5ef2aSThomas Huth break;
2751fcf5ef2aSThomas Huth case 0x28:
2752fcf5ef2aSThomas Huth /* LDL */
27535ffcb334SRichard Henderson gen_load_int(ctx, ra, rb, disp16, MO_LESL, 0, 0);
2754fcf5ef2aSThomas Huth break;
2755fcf5ef2aSThomas Huth case 0x29:
2756fcf5ef2aSThomas Huth /* LDQ */
2757fc313c64SFrédéric Pétrot gen_load_int(ctx, ra, rb, disp16, MO_LEUQ, 0, 0);
2758fcf5ef2aSThomas Huth break;
2759fcf5ef2aSThomas Huth case 0x2A:
2760fcf5ef2aSThomas Huth /* LDL_L */
276133948b68SRichard Henderson gen_load_int(ctx, ra, rb, disp16, MO_LESL | MO_ALIGN, 0, 1);
2762fcf5ef2aSThomas Huth break;
2763fcf5ef2aSThomas Huth case 0x2B:
2764fcf5ef2aSThomas Huth /* LDQ_L */
276533948b68SRichard Henderson gen_load_int(ctx, ra, rb, disp16, MO_LEUQ | MO_ALIGN, 0, 1);
2766fcf5ef2aSThomas Huth break;
2767fcf5ef2aSThomas Huth case 0x2C:
2768fcf5ef2aSThomas Huth /* STL */
27695ffcb334SRichard Henderson gen_store_int(ctx, ra, rb, disp16, MO_LEUL, 0);
2770fcf5ef2aSThomas Huth break;
2771fcf5ef2aSThomas Huth case 0x2D:
2772fcf5ef2aSThomas Huth /* STQ */
2773fc313c64SFrédéric Pétrot gen_store_int(ctx, ra, rb, disp16, MO_LEUQ, 0);
2774fcf5ef2aSThomas Huth break;
2775fcf5ef2aSThomas Huth case 0x2E:
2776fcf5ef2aSThomas Huth /* STL_C */
2777fcf5ef2aSThomas Huth ret = gen_store_conditional(ctx, ra, rb, disp16,
277833948b68SRichard Henderson ctx->mem_idx, MO_LESL | MO_ALIGN);
2779fcf5ef2aSThomas Huth break;
2780fcf5ef2aSThomas Huth case 0x2F:
2781fcf5ef2aSThomas Huth /* STQ_C */
2782fcf5ef2aSThomas Huth ret = gen_store_conditional(ctx, ra, rb, disp16,
278333948b68SRichard Henderson ctx->mem_idx, MO_LEUQ | MO_ALIGN);
2784fcf5ef2aSThomas Huth break;
2785fcf5ef2aSThomas Huth case 0x30:
2786fcf5ef2aSThomas Huth /* BR */
2787fcf5ef2aSThomas Huth ret = gen_bdirect(ctx, ra, disp21);
2788fcf5ef2aSThomas Huth break;
2789fcf5ef2aSThomas Huth case 0x31: /* FBEQ */
27909d14a042SRichard Henderson REQUIRE_FEN;
2791fcf5ef2aSThomas Huth ret = gen_fbcond(ctx, TCG_COND_EQ, ra, disp21);
2792fcf5ef2aSThomas Huth break;
2793fcf5ef2aSThomas Huth case 0x32: /* FBLT */
27949d14a042SRichard Henderson REQUIRE_FEN;
2795fcf5ef2aSThomas Huth ret = gen_fbcond(ctx, TCG_COND_LT, ra, disp21);
2796fcf5ef2aSThomas Huth break;
2797fcf5ef2aSThomas Huth case 0x33: /* FBLE */
27989d14a042SRichard Henderson REQUIRE_FEN;
2799fcf5ef2aSThomas Huth ret = gen_fbcond(ctx, TCG_COND_LE, ra, disp21);
2800fcf5ef2aSThomas Huth break;
2801fcf5ef2aSThomas Huth case 0x34:
2802fcf5ef2aSThomas Huth /* BSR */
2803fcf5ef2aSThomas Huth ret = gen_bdirect(ctx, ra, disp21);
2804fcf5ef2aSThomas Huth break;
2805fcf5ef2aSThomas Huth case 0x35: /* FBNE */
28069d14a042SRichard Henderson REQUIRE_FEN;
2807fcf5ef2aSThomas Huth ret = gen_fbcond(ctx, TCG_COND_NE, ra, disp21);
2808fcf5ef2aSThomas Huth break;
2809fcf5ef2aSThomas Huth case 0x36: /* FBGE */
28109d14a042SRichard Henderson REQUIRE_FEN;
2811fcf5ef2aSThomas Huth ret = gen_fbcond(ctx, TCG_COND_GE, ra, disp21);
2812fcf5ef2aSThomas Huth break;
2813fcf5ef2aSThomas Huth case 0x37: /* FBGT */
28149d14a042SRichard Henderson REQUIRE_FEN;
2815fcf5ef2aSThomas Huth ret = gen_fbcond(ctx, TCG_COND_GT, ra, disp21);
2816fcf5ef2aSThomas Huth break;
2817fcf5ef2aSThomas Huth case 0x38:
2818fcf5ef2aSThomas Huth /* BLBC */
2819c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_TSTEQ, ra, disp21);
2820fcf5ef2aSThomas Huth break;
2821fcf5ef2aSThomas Huth case 0x39:
2822fcf5ef2aSThomas Huth /* BEQ */
2823c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_EQ, ra, disp21);
2824fcf5ef2aSThomas Huth break;
2825fcf5ef2aSThomas Huth case 0x3A:
2826fcf5ef2aSThomas Huth /* BLT */
2827c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_LT, ra, disp21);
2828fcf5ef2aSThomas Huth break;
2829fcf5ef2aSThomas Huth case 0x3B:
2830fcf5ef2aSThomas Huth /* BLE */
2831c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_LE, ra, disp21);
2832fcf5ef2aSThomas Huth break;
2833fcf5ef2aSThomas Huth case 0x3C:
2834fcf5ef2aSThomas Huth /* BLBS */
2835c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_TSTNE, ra, disp21);
2836fcf5ef2aSThomas Huth break;
2837fcf5ef2aSThomas Huth case 0x3D:
2838fcf5ef2aSThomas Huth /* BNE */
2839c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_NE, ra, disp21);
2840fcf5ef2aSThomas Huth break;
2841fcf5ef2aSThomas Huth case 0x3E:
2842fcf5ef2aSThomas Huth /* BGE */
2843c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_GE, ra, disp21);
2844fcf5ef2aSThomas Huth break;
2845fcf5ef2aSThomas Huth case 0x3F:
2846fcf5ef2aSThomas Huth /* BGT */
2847c66ba978SRichard Henderson ret = gen_bcond(ctx, TCG_COND_GT, ra, disp21);
2848fcf5ef2aSThomas Huth break;
2849fcf5ef2aSThomas Huth invalid_opc:
2850fcf5ef2aSThomas Huth ret = gen_invalid(ctx);
2851fcf5ef2aSThomas Huth break;
28529d14a042SRichard Henderson raise_fen:
28539d14a042SRichard Henderson ret = gen_excp(ctx, EXCP_FEN, 0);
28549d14a042SRichard Henderson break;
2855fcf5ef2aSThomas Huth }
2856fcf5ef2aSThomas Huth
2857fcf5ef2aSThomas Huth return ret;
2858fcf5ef2aSThomas Huth }
2859fcf5ef2aSThomas Huth
alpha_tr_init_disas_context(DisasContextBase * dcbase,CPUState * cpu)2860b542683dSEmilio G. Cota static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
2861fcf5ef2aSThomas Huth {
286299a92b94SRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base);
2863b77af26eSRichard Henderson CPUAlphaState *env = cpu_env(cpu);
28643fd3442aSRichard Henderson int64_t bound;
2865fcf5ef2aSThomas Huth
286699a92b94SRichard Henderson ctx->tbflags = ctx->base.tb->flags;
286732a8ea12SRichard Henderson ctx->mem_idx = alpha_env_mmu_index(env);
2868*23bb0863SRichard Henderson ctx->pcrel = ctx->base.tb->cflags & CF_PCREL;
286999a92b94SRichard Henderson ctx->implver = env->implver;
287099a92b94SRichard Henderson ctx->amask = env->amask;
2871fcf5ef2aSThomas Huth
2872fcf5ef2aSThomas Huth #ifdef CONFIG_USER_ONLY
287399a92b94SRichard Henderson ctx->ir = cpu_std_ir;
2874fed14246SRichard Henderson ctx->unalign = (ctx->tbflags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN);
2875fcf5ef2aSThomas Huth #else
287699a92b94SRichard Henderson ctx->palbr = env->palbr;
287799a92b94SRichard Henderson ctx->ir = (ctx->tbflags & ENV_FLAG_PAL_MODE ? cpu_pal_ir : cpu_std_ir);
2878fcf5ef2aSThomas Huth #endif
2879fcf5ef2aSThomas Huth
2880fcf5ef2aSThomas Huth /* ??? Every TB begins with unset rounding mode, to be initialized on
2881fcf5ef2aSThomas Huth the first fp insn of the TB. Alternately we could define a proper
2882fcf5ef2aSThomas Huth default for every TB (e.g. QUAL_RM_N or QUAL_RM_D) and make sure
2883fcf5ef2aSThomas Huth to reset the FP_STATUS to that default at the end of any TB that
28848b81968cSMichael Tokarev changes the default. We could even (gasp) dynamically figure out
2885fcf5ef2aSThomas Huth what default would be most efficient given the running program. */
288699a92b94SRichard Henderson ctx->tb_rm = -1;
2887fcf5ef2aSThomas Huth /* Similarly for flush-to-zero. */
288899a92b94SRichard Henderson ctx->tb_ftz = -1;
2889fcf5ef2aSThomas Huth
2890f764718dSRichard Henderson ctx->zero = NULL;
2891f764718dSRichard Henderson ctx->sink = NULL;
2892fcf5ef2aSThomas Huth
289399a92b94SRichard Henderson /* Bound the number of insns to execute to those left on the page. */
28943fd3442aSRichard Henderson bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
2895b542683dSEmilio G. Cota ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
2896fcf5ef2aSThomas Huth }
2897fcf5ef2aSThomas Huth
alpha_tr_tb_start(DisasContextBase * db,CPUState * cpu)289899a92b94SRichard Henderson static void alpha_tr_tb_start(DisasContextBase *db, CPUState *cpu)
289999a92b94SRichard Henderson {
290099a92b94SRichard Henderson }
29018aa5c65fSRichard Henderson
alpha_tr_insn_start(DisasContextBase * dcbase,CPUState * cpu)290299a92b94SRichard Henderson static void alpha_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
290399a92b94SRichard Henderson {
2904*23bb0863SRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base);
2905*23bb0863SRichard Henderson
2906*23bb0863SRichard Henderson if (ctx->pcrel) {
2907*23bb0863SRichard Henderson tcg_gen_insn_start(dcbase->pc_next & ~TARGET_PAGE_MASK);
2908*23bb0863SRichard Henderson } else {
290999a92b94SRichard Henderson tcg_gen_insn_start(dcbase->pc_next);
291099a92b94SRichard Henderson }
2911*23bb0863SRichard Henderson }
2912fcf5ef2aSThomas Huth
alpha_tr_translate_insn(DisasContextBase * dcbase,CPUState * cpu)291399a92b94SRichard Henderson static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
291499a92b94SRichard Henderson {
291599a92b94SRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base);
291650cb36ceSPhilippe Mathieu-Daudé uint32_t insn = translator_ldl(cpu_env(cpu), &ctx->base,
291750cb36ceSPhilippe Mathieu-Daudé ctx->base.pc_next);
2918fcf5ef2aSThomas Huth
291999a92b94SRichard Henderson ctx->base.pc_next += 4;
292099a92b94SRichard Henderson ctx->base.is_jmp = translate_one(ctx, insn);
292199a92b94SRichard Henderson
292299a92b94SRichard Henderson free_context_temps(ctx);
2923fcf5ef2aSThomas Huth }
2924fcf5ef2aSThomas Huth
alpha_tr_tb_stop(DisasContextBase * dcbase,CPUState * cpu)292599a92b94SRichard Henderson static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
292699a92b94SRichard Henderson {
292799a92b94SRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base);
292899a92b94SRichard Henderson
292999a92b94SRichard Henderson switch (ctx->base.is_jmp) {
29303de811c6SRichard Henderson case DISAS_NORETURN:
2931fcf5ef2aSThomas Huth break;
29323de811c6SRichard Henderson case DISAS_TOO_MANY:
293382b60d25SRichard Henderson gen_goto_tb(ctx, 0, 0);
293482b60d25SRichard Henderson break;
29353de811c6SRichard Henderson case DISAS_PC_STALE:
2936b1a3eacfSRichard Henderson gen_pc_disp(ctx, cpu_pc, 0);
2937fcf5ef2aSThomas Huth /* FALLTHRU */
29383de811c6SRichard Henderson case DISAS_PC_UPDATED:
29397f11636dSEmilio G. Cota tcg_gen_lookup_and_goto_ptr();
294054e1d4edSRichard Henderson break;
29413de811c6SRichard Henderson case DISAS_PC_UPDATED_NOCHAIN:
294207ea28b4SRichard Henderson tcg_gen_exit_tb(NULL, 0);
2943fcf5ef2aSThomas Huth break;
2944fcf5ef2aSThomas Huth default:
29452d826cdcSRichard Henderson g_assert_not_reached();
2946fcf5ef2aSThomas Huth }
2947fcf5ef2aSThomas Huth }
294899a92b94SRichard Henderson
294999a92b94SRichard Henderson static const TranslatorOps alpha_tr_ops = {
295099a92b94SRichard Henderson .init_disas_context = alpha_tr_init_disas_context,
295199a92b94SRichard Henderson .tb_start = alpha_tr_tb_start,
295299a92b94SRichard Henderson .insn_start = alpha_tr_insn_start,
295399a92b94SRichard Henderson .translate_insn = alpha_tr_translate_insn,
295499a92b94SRichard Henderson .tb_stop = alpha_tr_tb_stop,
295599a92b94SRichard Henderson };
295699a92b94SRichard Henderson
gen_intermediate_code(CPUState * cpu,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)2957597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int *max_insns,
295832f0c394SAnton Johansson vaddr pc, void *host_pc)
295999a92b94SRichard Henderson {
296099a92b94SRichard Henderson DisasContext dc;
2961306c8721SRichard Henderson translator_loop(cpu, tb, max_insns, pc, host_pc, &alpha_tr_ops, &dc.base);
2962fcf5ef2aSThomas Huth }
2963