blob: b3a4d61d0a224f8bedb0a2c35c1251f7742f15bf [file] [log] [blame]
ths81700282007-10-08 12:49:08 +00001/*
2 * CRIS emulation for qemu: main translation routines.
3 *
edgar_igl05ba7d52008-03-14 01:11:25 +00004 * Copyright (c) 2008 AXIS Communications AB
ths81700282007-10-08 12:49:08 +00005 * Written by Edgar E. Iglesias.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
Chetan Pantbf1b52d2020-10-23 12:16:48 +000010 * version 2.1 of the License, or (at your option) any later version.
ths81700282007-10-08 12:49:08 +000011 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
Blue Swirl8167ee82009-07-16 20:47:01 +000018 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
ths81700282007-10-08 12:49:08 +000019 */
20
edgar_iglb41f7df2008-05-02 22:16:17 +000021/*
22 * FIXME:
edgar_iglcf1d97f2008-05-13 10:59:14 +000023 * The condition code translation is in need of attention.
edgar_iglb41f7df2008-05-02 22:16:17 +000024 */
25
Peter Maydell23b0d7d2016-01-26 18:17:24 +000026#include "qemu/osdep.h"
ths81700282007-10-08 12:49:08 +000027#include "cpu.h"
Paolo Bonzini76cad712012-10-24 11:12:21 +020028#include "disas/disas.h"
Paolo Bonzini63c91552016-03-15 13:18:37 +010029#include "exec/exec-all.h"
Philippe Mathieu-Daudédcb32f12020-01-01 12:23:00 +010030#include "tcg/tcg-op.h"
Richard Henderson2ef61752014-04-07 22:31:41 -070031#include "exec/helper-proto.h"
edgar_igl52819662009-01-26 22:21:30 +000032#include "mmu.h"
Paolo Bonzinif08b6172014-03-28 19:42:10 +010033#include "exec/cpu_ldst.h"
Lluís Vilanova77fc6f52017-07-14 11:21:37 +030034#include "exec/translator.h"
ths81700282007-10-08 12:49:08 +000035#include "crisv32-decode.h"
Markus Armbruster90c84c52019-04-17 21:18:02 +020036#include "qemu/qemu-print.h"
Richard Henderson2ef61752014-04-07 22:31:41 -070037#include "exec/helper-gen.h"
Paolo Bonzini508127e2016-01-07 16:55:28 +030038#include "exec/log.h"
Lluís Vilanovaa7e30d82014-05-30 14:12:25 +020039
Richard Hendersond53106c2023-03-31 10:37:04 -070040#define HELPER_H "helper.h"
41#include "exec/helper-info.c.inc"
42#undef HELPER_H
43
Lluís Vilanovaa7e30d82014-05-30 14:12:25 +020044
ths81700282007-10-08 12:49:08 +000045#define DISAS_CRIS 0
46#if DISAS_CRIS
aliguori93fcfe32009-01-15 22:34:14 +000047# define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
ths81700282007-10-08 12:49:08 +000048#else
aliguorid12d51d2009-01-15 21:48:06 +000049# define LOG_DIS(...) do { } while (0)
ths81700282007-10-08 12:49:08 +000050#endif
51
edgar_iglb41f7df2008-05-02 22:16:17 +000052#define D(x)
ths81700282007-10-08 12:49:08 +000053#define BUG() (gen_BUG(dc, __FILE__, __LINE__))
54#define BUG_ON(x) ({if (x) BUG();})
55
Richard Hendersonc9674752021-06-22 07:50:12 -070056/*
57 * Target-specific is_jmp field values
58 */
59/* Only pc was modified dynamically */
60#define DISAS_JUMP DISAS_TARGET_0
61/* Cpu state was modified dynamically, including pc */
62#define DISAS_UPDATE DISAS_TARGET_1
63/* Cpu state was modified dynamically, excluding pc -- use npc */
64#define DISAS_UPDATE_NEXT DISAS_TARGET_2
Richard Henderson31737152021-06-20 13:43:35 -070065/* PC update for delayed branch, see cpustate_changed otherwise */
66#define DISAS_DBRANCH DISAS_TARGET_3
edgar_igl4f400ab2008-02-28 09:37:58 +000067
ths81700282007-10-08 12:49:08 +000068/* Used by the decoder. */
69#define EXTRACT_FIELD(src, start, end) \
70 (((src) >> start) & ((1 << (end - start + 1)) - 1))
71
72#define CC_MASK_NZ 0xc
73#define CC_MASK_NZV 0xe
74#define CC_MASK_NZVC 0xf
75#define CC_MASK_RNZV 0x10e
76
edgar_igl9b32fbf2008-10-07 22:54:52 +000077static TCGv cpu_R[16];
78static TCGv cpu_PR[16];
79static TCGv cc_x;
80static TCGv cc_src;
81static TCGv cc_dest;
82static TCGv cc_result;
83static TCGv cc_op;
84static TCGv cc_size;
85static TCGv cc_mask;
edgar_igl05ba7d52008-03-14 01:11:25 +000086
edgar_igl9b32fbf2008-10-07 22:54:52 +000087static TCGv env_btaken;
88static TCGv env_btarget;
89static TCGv env_pc;
edgar_iglb41f7df2008-05-02 22:16:17 +000090
ths81700282007-10-08 12:49:08 +000091/* This is the state at translation time. */
92typedef struct DisasContext {
Richard Henderson67f69c42021-06-19 19:17:40 -070093 DisasContextBase base;
94
Andreas Färber0dd106c2013-09-03 18:42:27 +020095 CRISCPU *cpu;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +040096 target_ulong pc, ppc;
Richard Henderson97fc0c22024-01-28 15:05:06 +100097 int mem_index;
ths81700282007-10-08 12:49:08 +000098
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +040099 /* Decoder. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +0200100 unsigned int (*decoder)(CPUCRISState *env, struct DisasContext *dc);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400101 uint32_t ir;
102 uint32_t opcode;
103 unsigned int op1;
104 unsigned int op2;
105 unsigned int zsize, zzsize;
106 unsigned int mode;
107 unsigned int postinc;
ths81700282007-10-08 12:49:08 +0000108
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400109 unsigned int size;
110 unsigned int src;
111 unsigned int dst;
112 unsigned int cond;
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +0100113
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400114 int update_cc;
115 int cc_op;
116 int cc_size;
117 uint32_t cc_mask;
ths81700282007-10-08 12:49:08 +0000118
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400119 int cc_size_uptodate; /* -1 invalid or last written value. */
edgar_igl30abcfc2008-05-27 21:10:56 +0000120
Veres Lajos67cc32e2015-09-08 22:45:14 +0100121 int cc_x_uptodate; /* 1 - ccs, 2 - known | X_FLAG. 0 not up-to-date. */
122 int flags_uptodate; /* Whether or not $ccs is up-to-date. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400123 int flags_x;
edgar_igl30abcfc2008-05-27 21:10:56 +0000124
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400125 int clear_x; /* Clear x after this insn? */
126 int clear_prefix; /* Clear prefix after this insn? */
127 int clear_locked_irq; /* Clear the irq lockout. */
128 int cpustate_changed;
129 unsigned int tb_flags; /* tb dependent flags. */
ths81700282007-10-08 12:49:08 +0000130
Edgar E. Iglesias5cabc5c2011-01-10 23:24:36 +0100131#define JMP_NOJMP 0
132#define JMP_DIRECT 1
133#define JMP_DIRECT_CC 2
134#define JMP_INDIRECT 3
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400135 int jmp; /* 0=nojmp, 1=direct, 2=indirect. */
136 uint32_t jmp_pc;
edgar_igl2a44f7f2008-06-06 11:23:28 +0000137
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400138 int delayed_branch;
ths81700282007-10-08 12:49:08 +0000139} DisasContext;
140
blueswir17ccfb2e2008-09-14 06:45:34 +0000141static void gen_BUG(DisasContext *dc, const char *file, int line)
ths81700282007-10-08 12:49:08 +0000142{
Thomas Huthba3fa392018-10-09 09:40:33 +0200143 cpu_abort(CPU(dc->cpu), "%s:%d pc=%x\n", file, line, dc->pc);
ths81700282007-10-08 12:49:08 +0000144}
145
Richard Henderson5899ce62021-06-19 20:57:31 -0700146static const char * const regnames_v32[] =
edgar_igla825e702008-03-16 16:51:58 +0000147{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400148 "$r0", "$r1", "$r2", "$r3",
149 "$r4", "$r5", "$r6", "$r7",
150 "$r8", "$r9", "$r10", "$r11",
151 "$r12", "$r13", "$sp", "$acr",
edgar_igla825e702008-03-16 16:51:58 +0000152};
Richard Henderson5899ce62021-06-19 20:57:31 -0700153
154static const char * const pregnames_v32[] =
edgar_igla825e702008-03-16 16:51:58 +0000155{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400156 "$bz", "$vr", "$pid", "$srs",
157 "$wz", "$exs", "$eda", "$mof",
158 "$dz", "$ebp", "$erp", "$srp",
159 "$nrp", "$ccs", "$usp", "$spc",
edgar_igla825e702008-03-16 16:51:58 +0000160};
161
edgar_igl05ba7d52008-03-14 01:11:25 +0000162/* We need this table to handle preg-moves with implicit width. */
Richard Henderson5899ce62021-06-19 20:57:31 -0700163static const int preg_sizes[] = {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400164 1, /* bz. */
165 1, /* vr. */
166 4, /* pid. */
167 1, /* srs. */
168 2, /* wz. */
169 4, 4, 4,
170 4, 4, 4, 4,
171 4, 4, 4, 4,
edgar_igl05ba7d52008-03-14 01:11:25 +0000172};
173
174#define t_gen_mov_TN_env(tn, member) \
Richard Hendersonad75a512023-09-13 16:37:36 -0700175 tcg_gen_ld_tl(tn, tcg_env, offsetof(CPUCRISState, member))
edgar_igl05ba7d52008-03-14 01:11:25 +0000176#define t_gen_mov_env_TN(member, tn) \
Richard Hendersonad75a512023-09-13 16:37:36 -0700177 tcg_gen_st_tl(tn, tcg_env, offsetof(CPUCRISState, member))
Stefan Sandstromfd52dee2021-02-19 13:44:16 +0100178#define t_gen_movi_env_TN(member, c) \
Richard Hendersonab554f12023-02-25 12:44:04 -1000179 t_gen_mov_env_TN(member, tcg_constant_tl(c))
edgar_igl05ba7d52008-03-14 01:11:25 +0000180
181static inline void t_gen_mov_TN_preg(TCGv tn, int r)
182{
zhanghailiangfae38222014-11-17 13:57:34 +0800183 assert(r >= 0 && r <= 15);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400184 if (r == PR_BZ || r == PR_WZ || r == PR_DZ) {
Stefan Sandstromfd52dee2021-02-19 13:44:16 +0100185 tcg_gen_movi_tl(tn, 0);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400186 } else if (r == PR_VR) {
Stefan Sandstromfd52dee2021-02-19 13:44:16 +0100187 tcg_gen_movi_tl(tn, 32);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400188 } else {
189 tcg_gen_mov_tl(tn, cpu_PR[r]);
190 }
edgar_igl05ba7d52008-03-14 01:11:25 +0000191}
edgar_iglcf1d97f2008-05-13 10:59:14 +0000192static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn)
edgar_igl05ba7d52008-03-14 01:11:25 +0000193{
zhanghailiangfae38222014-11-17 13:57:34 +0800194 assert(r >= 0 && r <= 15);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400195 if (r == PR_BZ || r == PR_WZ || r == PR_DZ) {
196 return;
197 } else if (r == PR_SRS) {
198 tcg_gen_andi_tl(cpu_PR[r], tn, 3);
199 } else {
200 if (r == PR_PID) {
Richard Hendersonad75a512023-09-13 16:37:36 -0700201 gen_helper_tlb_flush_pid(tcg_env, tn);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400202 }
203 if (dc->tb_flags & S_FLAG && r == PR_SPC) {
Richard Hendersonad75a512023-09-13 16:37:36 -0700204 gen_helper_spc_write(tcg_env, tn);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400205 } else if (r == PR_CCS) {
206 dc->cpustate_changed = 1;
207 }
208 tcg_gen_mov_tl(cpu_PR[r], tn);
209 }
edgar_igl05ba7d52008-03-14 01:11:25 +0000210}
211
Edgar E. Iglesias18845332010-06-16 13:46:15 +0200212/* Sign extend at translation time. */
213static int sign_extend(unsigned int val, unsigned int width)
214{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400215 int sval;
Edgar E. Iglesias18845332010-06-16 13:46:15 +0200216
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400217 /* LSL. */
218 val <<= 31 - width;
219 sval = val;
220 /* ASR. */
221 sval >>= 31 - width;
222 return sval;
Edgar E. Iglesias18845332010-06-16 13:46:15 +0200223}
224
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +0200225static int cris_fetch(CPUCRISState *env, DisasContext *dc, uint32_t addr,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400226 unsigned int size, unsigned int sign)
Edgar E. Iglesias7de141c2010-06-16 11:49:30 +0200227{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400228 int r;
Edgar E. Iglesias7de141c2010-06-16 11:49:30 +0200229
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400230 switch (size) {
231 case 4:
232 {
233 r = cpu_ldl_code(env, addr);
234 break;
235 }
236 case 2:
237 {
238 if (sign) {
239 r = cpu_ldsw_code(env, addr);
240 } else {
241 r = cpu_lduw_code(env, addr);
242 }
243 break;
244 }
245 case 1:
246 {
247 if (sign) {
248 r = cpu_ldsb_code(env, addr);
249 } else {
250 r = cpu_ldub_code(env, addr);
251 }
252 break;
253 }
254 default:
Andreas Färber0dd106c2013-09-03 18:42:27 +0200255 cpu_abort(CPU(dc->cpu), "Invalid fetch size %d\n", size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400256 break;
257 }
258 return r;
Edgar E. Iglesias7de141c2010-06-16 11:49:30 +0200259}
260
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +0100261static void cris_lock_irq(DisasContext *dc)
262{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400263 dc->clear_locked_irq = 0;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +0100264 t_gen_movi_env_TN(locked_irq, 1);
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +0100265}
266
edgar_igldceaf392008-05-07 15:24:53 +0000267static inline void t_gen_raise_exception(uint32_t index)
edgar_igl05ba7d52008-03-14 01:11:25 +0000268{
Richard Hendersonad75a512023-09-13 16:37:36 -0700269 gen_helper_raise_exception(tcg_env, tcg_constant_i32(index));
edgar_igl05ba7d52008-03-14 01:11:25 +0000270}
271
272static void t_gen_lsl(TCGv d, TCGv a, TCGv b)
273{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400274 TCGv t0, t_31;
edgar_igl05ba7d52008-03-14 01:11:25 +0000275
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400276 t0 = tcg_temp_new();
Richard Hendersonab554f12023-02-25 12:44:04 -1000277 t_31 = tcg_constant_tl(31);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400278 tcg_gen_shl_tl(d, a, b);
edgar_igl7dcfb082008-10-27 12:39:30 +0000279
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400280 tcg_gen_sub_tl(t0, t_31, b);
281 tcg_gen_sar_tl(t0, t0, t_31);
282 tcg_gen_and_tl(t0, t0, d);
283 tcg_gen_xor_tl(d, d, t0);
edgar_igl05ba7d52008-03-14 01:11:25 +0000284}
285
286static void t_gen_lsr(TCGv d, TCGv a, TCGv b)
287{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400288 TCGv t0, t_31;
edgar_igl05ba7d52008-03-14 01:11:25 +0000289
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400290 t0 = tcg_temp_new();
291 t_31 = tcg_temp_new();
292 tcg_gen_shr_tl(d, a, b);
edgar_igl7dcfb082008-10-27 12:39:30 +0000293
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400294 tcg_gen_movi_tl(t_31, 31);
295 tcg_gen_sub_tl(t0, t_31, b);
296 tcg_gen_sar_tl(t0, t0, t_31);
297 tcg_gen_and_tl(t0, t0, d);
298 tcg_gen_xor_tl(d, d, t0);
edgar_igl05ba7d52008-03-14 01:11:25 +0000299}
300
301static void t_gen_asr(TCGv d, TCGv a, TCGv b)
302{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400303 TCGv t0, t_31;
edgar_igl05ba7d52008-03-14 01:11:25 +0000304
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400305 t0 = tcg_temp_new();
306 t_31 = tcg_temp_new();
307 tcg_gen_sar_tl(d, a, b);
edgar_igl7dcfb082008-10-27 12:39:30 +0000308
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400309 tcg_gen_movi_tl(t_31, 31);
310 tcg_gen_sub_tl(t0, t_31, b);
311 tcg_gen_sar_tl(t0, t0, t_31);
312 tcg_gen_or_tl(d, d, t0);
edgar_igl05ba7d52008-03-14 01:11:25 +0000313}
314
edgar_igl30abcfc2008-05-27 21:10:56 +0000315static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
edgar_iglaae6b322008-05-03 21:34:39 +0000316{
Richard Henderson88174012015-09-02 11:38:10 -0700317 TCGv t = tcg_temp_new();
edgar_iglaae6b322008-05-03 21:34:39 +0000318
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400319 /*
320 * d <<= 1
321 * if (d >= s)
322 * d -= s;
323 */
324 tcg_gen_shli_tl(d, a, 1);
Richard Henderson88174012015-09-02 11:38:10 -0700325 tcg_gen_sub_tl(t, d, b);
326 tcg_gen_movcond_tl(TCG_COND_GEU, d, d, b, t, d);
edgar_iglaae6b322008-05-03 21:34:39 +0000327}
328
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +0100329static void t_gen_cris_mstep(TCGv d, TCGv a, TCGv b, TCGv ccs)
330{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400331 TCGv t;
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +0100332
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400333 /*
334 * d <<= 1
335 * if (n)
336 * d += s;
337 */
338 t = tcg_temp_new();
339 tcg_gen_shli_tl(d, a, 1);
340 tcg_gen_shli_tl(t, ccs, 31 - 3);
341 tcg_gen_sari_tl(t, t, 31);
342 tcg_gen_and_tl(t, t, b);
343 tcg_gen_add_tl(d, d, t);
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +0100344}
345
Michael Tokarev8b819682023-07-14 14:23:51 +0300346/* Extended arithmetic on CRIS. */
edgar_igl3157a0a2008-03-15 20:45:05 +0000347static inline void t_gen_add_flag(TCGv d, int flag)
348{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400349 TCGv c;
edgar_igl3157a0a2008-03-15 20:45:05 +0000350
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400351 c = tcg_temp_new();
352 t_gen_mov_TN_preg(c, PR_CCS);
353 /* Propagate carry into d. */
354 tcg_gen_andi_tl(c, c, 1 << flag);
355 if (flag) {
356 tcg_gen_shri_tl(c, c, flag);
357 }
358 tcg_gen_add_tl(d, d, c);
edgar_igl3157a0a2008-03-15 20:45:05 +0000359}
360
edgar_igl30abcfc2008-05-27 21:10:56 +0000361static inline void t_gen_addx_carry(DisasContext *dc, TCGv d)
edgar_igl3157a0a2008-03-15 20:45:05 +0000362{
Richard Henderson0ce97a32021-06-22 08:18:12 -0700363 if (dc->flags_x) {
364 TCGv c = tcg_temp_new();
edgar_igl3157a0a2008-03-15 20:45:05 +0000365
Richard Henderson0ce97a32021-06-22 08:18:12 -0700366 t_gen_mov_TN_preg(c, PR_CCS);
367 /* C flag is already at bit 0. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400368 tcg_gen_andi_tl(c, c, C_FLAG);
Richard Henderson0ce97a32021-06-22 08:18:12 -0700369 tcg_gen_add_tl(d, d, c);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400370 }
edgar_igl3157a0a2008-03-15 20:45:05 +0000371}
372
edgar_igla39f8f32008-05-12 07:57:23 +0000373static inline void t_gen_subx_carry(DisasContext *dc, TCGv d)
edgar_igl3157a0a2008-03-15 20:45:05 +0000374{
Richard Henderson0ce97a32021-06-22 08:18:12 -0700375 if (dc->flags_x) {
376 TCGv c = tcg_temp_new();
edgar_igl3157a0a2008-03-15 20:45:05 +0000377
Richard Henderson0ce97a32021-06-22 08:18:12 -0700378 t_gen_mov_TN_preg(c, PR_CCS);
379 /* C flag is already at bit 0. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400380 tcg_gen_andi_tl(c, c, C_FLAG);
Richard Henderson0ce97a32021-06-22 08:18:12 -0700381 tcg_gen_sub_tl(d, d, c);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400382 }
edgar_igl3157a0a2008-03-15 20:45:05 +0000383}
384
385/* Swap the two bytes within each half word of the s operand.
386 T0 = ((T0 << 8) & 0xff00ff00) | ((T0 >> 8) & 0x00ff00ff) */
387static inline void t_gen_swapb(TCGv d, TCGv s)
388{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400389 TCGv t, org_s;
edgar_igl3157a0a2008-03-15 20:45:05 +0000390
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400391 t = tcg_temp_new();
392 org_s = tcg_temp_new();
edgar_igl3157a0a2008-03-15 20:45:05 +0000393
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400394 /* d and s may refer to the same object. */
395 tcg_gen_mov_tl(org_s, s);
396 tcg_gen_shli_tl(t, org_s, 8);
397 tcg_gen_andi_tl(d, t, 0xff00ff00);
398 tcg_gen_shri_tl(t, org_s, 8);
399 tcg_gen_andi_tl(t, t, 0x00ff00ff);
400 tcg_gen_or_tl(d, d, t);
edgar_igl3157a0a2008-03-15 20:45:05 +0000401}
402
403/* Swap the halfwords of the s operand. */
404static inline void t_gen_swapw(TCGv d, TCGv s)
405{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400406 TCGv t;
407 /* d and s refer the same object. */
408 t = tcg_temp_new();
409 tcg_gen_mov_tl(t, s);
410 tcg_gen_shli_tl(d, t, 16);
411 tcg_gen_shri_tl(t, t, 16);
412 tcg_gen_or_tl(d, d, t);
edgar_igl3157a0a2008-03-15 20:45:05 +0000413}
414
Philippe Mathieu-Daudé27756162023-08-23 16:55:42 +0200415/*
416 * Reverse the bits within each byte.
417 *
418 * T0 = ((T0 << 7) & 0x80808080)
419 * | ((T0 << 5) & 0x40404040)
420 * | ((T0 << 3) & 0x20202020)
421 * | ((T0 << 1) & 0x10101010)
422 * | ((T0 >> 1) & 0x08080808)
423 * | ((T0 >> 3) & 0x04040404)
424 * | ((T0 >> 5) & 0x02020202)
425 * | ((T0 >> 7) & 0x01010101);
edgar_igl3157a0a2008-03-15 20:45:05 +0000426 */
Richard Henderson5899ce62021-06-19 20:57:31 -0700427static void t_gen_swapr(TCGv d, TCGv s)
edgar_igl3157a0a2008-03-15 20:45:05 +0000428{
Richard Henderson5899ce62021-06-19 20:57:31 -0700429 static const struct {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400430 int shift; /* LSL when positive, LSR when negative. */
431 uint32_t mask;
432 } bitrev[] = {
433 {7, 0x80808080},
434 {5, 0x40404040},
435 {3, 0x20202020},
436 {1, 0x10101010},
437 {-1, 0x08080808},
438 {-3, 0x04040404},
439 {-5, 0x02020202},
440 {-7, 0x01010101}
441 };
442 int i;
443 TCGv t, org_s;
edgar_igl3157a0a2008-03-15 20:45:05 +0000444
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400445 /* d and s refer the same object. */
446 t = tcg_temp_new();
447 org_s = tcg_temp_new();
448 tcg_gen_mov_tl(org_s, s);
edgar_igl3157a0a2008-03-15 20:45:05 +0000449
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400450 tcg_gen_shli_tl(t, org_s, bitrev[0].shift);
451 tcg_gen_andi_tl(d, t, bitrev[0].mask);
452 for (i = 1; i < ARRAY_SIZE(bitrev); i++) {
453 if (bitrev[i].shift >= 0) {
454 tcg_gen_shli_tl(t, org_s, bitrev[i].shift);
455 } else {
456 tcg_gen_shri_tl(t, org_s, -bitrev[i].shift);
457 }
458 tcg_gen_andi_tl(t, t, bitrev[i].mask);
459 tcg_gen_or_tl(d, d, t);
460 }
edgar_igl3157a0a2008-03-15 20:45:05 +0000461}
462
Richard Henderson06188c82021-06-20 11:39:52 -0700463static bool use_goto_tb(DisasContext *dc, target_ulong dest)
Sergey Fedorov90aa39a2016-04-09 01:00:23 +0300464{
Richard Hendersonca92d7f2021-06-20 16:05:53 -0700465 return translator_use_goto_tb(&dc->base, dest);
Sergey Fedorov90aa39a2016-04-09 01:00:23 +0300466}
467
ths81700282007-10-08 12:49:08 +0000468static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
469{
Sergey Fedorov90aa39a2016-04-09 01:00:23 +0300470 if (use_goto_tb(dc, dest)) {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400471 tcg_gen_goto_tb(n);
472 tcg_gen_movi_tl(env_pc, dest);
Richard Henderson67f69c42021-06-19 19:17:40 -0700473 tcg_gen_exit_tb(dc->base.tb, n);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400474 } else {
475 tcg_gen_movi_tl(env_pc, dest);
Richard Hendersone0a46202021-06-20 13:49:17 -0700476 tcg_gen_lookup_and_goto_ptr();
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400477 }
ths81700282007-10-08 12:49:08 +0000478}
479
edgar_igl05ba7d52008-03-14 01:11:25 +0000480static inline void cris_clear_x_flag(DisasContext *dc)
481{
Richard Henderson0ce97a32021-06-22 08:18:12 -0700482 if (dc->flags_x) {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400483 dc->flags_uptodate = 0;
484 }
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400485 dc->flags_x = 0;
edgar_igl05ba7d52008-03-14 01:11:25 +0000486}
487
edgar_igl30abcfc2008-05-27 21:10:56 +0000488static void cris_flush_cc_state(DisasContext *dc)
489{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400490 if (dc->cc_size_uptodate != dc->cc_size) {
491 tcg_gen_movi_tl(cc_size, dc->cc_size);
492 dc->cc_size_uptodate = dc->cc_size;
493 }
494 tcg_gen_movi_tl(cc_op, dc->cc_op);
495 tcg_gen_movi_tl(cc_mask, dc->cc_mask);
edgar_igl30abcfc2008-05-27 21:10:56 +0000496}
497
ths81700282007-10-08 12:49:08 +0000498static void cris_evaluate_flags(DisasContext *dc)
499{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400500 if (dc->flags_uptodate) {
501 return;
502 }
edgar_iglb41f7df2008-05-02 22:16:17 +0000503
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400504 cris_flush_cc_state(dc);
edgar_igl62318682009-01-07 23:38:41 +0000505
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400506 switch (dc->cc_op) {
507 case CC_OP_MCP:
Richard Hendersonad75a512023-09-13 16:37:36 -0700508 gen_helper_evaluate_flags_mcp(cpu_PR[PR_CCS], tcg_env,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400509 cpu_PR[PR_CCS], cc_src,
510 cc_dest, cc_result);
511 break;
512 case CC_OP_MULS:
Richard Hendersonad75a512023-09-13 16:37:36 -0700513 gen_helper_evaluate_flags_muls(cpu_PR[PR_CCS], tcg_env,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400514 cpu_PR[PR_CCS], cc_result,
515 cpu_PR[PR_MOF]);
516 break;
517 case CC_OP_MULU:
Richard Hendersonad75a512023-09-13 16:37:36 -0700518 gen_helper_evaluate_flags_mulu(cpu_PR[PR_CCS], tcg_env,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400519 cpu_PR[PR_CCS], cc_result,
520 cpu_PR[PR_MOF]);
521 break;
522 case CC_OP_MOVE:
523 case CC_OP_AND:
524 case CC_OP_OR:
525 case CC_OP_XOR:
526 case CC_OP_ASR:
527 case CC_OP_LSR:
528 case CC_OP_LSL:
529 switch (dc->cc_size) {
530 case 4:
531 gen_helper_evaluate_flags_move_4(cpu_PR[PR_CCS],
Richard Hendersonad75a512023-09-13 16:37:36 -0700532 tcg_env, cpu_PR[PR_CCS], cc_result);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400533 break;
534 case 2:
535 gen_helper_evaluate_flags_move_2(cpu_PR[PR_CCS],
Richard Hendersonad75a512023-09-13 16:37:36 -0700536 tcg_env, cpu_PR[PR_CCS], cc_result);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400537 break;
538 default:
Richard Hendersonad75a512023-09-13 16:37:36 -0700539 gen_helper_evaluate_flags(tcg_env);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400540 break;
edgar_igl62318682009-01-07 23:38:41 +0000541 }
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400542 break;
543 case CC_OP_FLAGS:
544 /* live. */
545 break;
546 case CC_OP_SUB:
547 case CC_OP_CMP:
548 if (dc->cc_size == 4) {
Richard Hendersonad75a512023-09-13 16:37:36 -0700549 gen_helper_evaluate_flags_sub_4(cpu_PR[PR_CCS], tcg_env,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400550 cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
551 } else {
Richard Hendersonad75a512023-09-13 16:37:36 -0700552 gen_helper_evaluate_flags(tcg_env);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400553 }
554
555 break;
556 default:
557 switch (dc->cc_size) {
558 case 4:
Richard Hendersonad75a512023-09-13 16:37:36 -0700559 gen_helper_evaluate_flags_alu_4(cpu_PR[PR_CCS], tcg_env,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400560 cpu_PR[PR_CCS], cc_src, cc_dest, cc_result);
561 break;
562 default:
Richard Hendersonad75a512023-09-13 16:37:36 -0700563 gen_helper_evaluate_flags(tcg_env);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400564 break;
565 }
566 break;
567 }
568
Richard Henderson0ce97a32021-06-22 08:18:12 -0700569 if (dc->flags_x) {
570 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], X_FLAG);
571 } else if (dc->cc_op == CC_OP_FLAGS) {
572 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400573 }
574 dc->flags_uptodate = 1;
ths81700282007-10-08 12:49:08 +0000575}
576
577static void cris_cc_mask(DisasContext *dc, unsigned int mask)
578{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400579 uint32_t ovl;
ths81700282007-10-08 12:49:08 +0000580
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400581 if (!mask) {
582 dc->update_cc = 0;
583 return;
584 }
edgar_igl2a44f7f2008-06-06 11:23:28 +0000585
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400586 /* Check if we need to evaluate the condition codes due to
587 CC overlaying. */
588 ovl = (dc->cc_mask ^ mask) & ~mask;
589 if (ovl) {
590 /* TODO: optimize this case. It trigs all the time. */
591 cris_evaluate_flags(dc);
592 }
593 dc->cc_mask = mask;
594 dc->update_cc = 1;
ths81700282007-10-08 12:49:08 +0000595}
596
edgar_iglb41f7df2008-05-02 22:16:17 +0000597static void cris_update_cc_op(DisasContext *dc, int op, int size)
ths81700282007-10-08 12:49:08 +0000598{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400599 dc->cc_op = op;
600 dc->cc_size = size;
601 dc->flags_uptodate = 0;
ths81700282007-10-08 12:49:08 +0000602}
603
edgar_igl30abcfc2008-05-27 21:10:56 +0000604static inline void cris_update_cc_x(DisasContext *dc)
ths81700282007-10-08 12:49:08 +0000605{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400606 /* Save the x flag state at the time of the cc snapshot. */
Richard Henderson0ce97a32021-06-22 08:18:12 -0700607 if (dc->cc_x_uptodate == (2 | dc->flags_x)) {
608 return;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400609 }
Richard Henderson0ce97a32021-06-22 08:18:12 -0700610 tcg_gen_movi_tl(cc_x, dc->flags_x);
611 dc->cc_x_uptodate = 2 | dc->flags_x;
edgar_igl30abcfc2008-05-27 21:10:56 +0000612}
613
614/* Update cc prior to executing ALU op. Needs source operands untouched. */
615static void cris_pre_alu_update_cc(DisasContext *dc, int op,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400616 TCGv dst, TCGv src, int size)
edgar_igl30abcfc2008-05-27 21:10:56 +0000617{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400618 if (dc->update_cc) {
619 cris_update_cc_op(dc, op, size);
620 tcg_gen_mov_tl(cc_src, src);
edgar_igl3157a0a2008-03-15 20:45:05 +0000621
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400622 if (op != CC_OP_MOVE
623 && op != CC_OP_AND
624 && op != CC_OP_OR
625 && op != CC_OP_XOR
626 && op != CC_OP_ASR
627 && op != CC_OP_LSR
628 && op != CC_OP_LSL) {
629 tcg_gen_mov_tl(cc_dest, dst);
630 }
edgar_igl30abcfc2008-05-27 21:10:56 +0000631
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400632 cris_update_cc_x(dc);
633 }
edgar_igl30abcfc2008-05-27 21:10:56 +0000634}
ths81700282007-10-08 12:49:08 +0000635
edgar_igl30abcfc2008-05-27 21:10:56 +0000636/* Update cc after executing ALU op. needs the result. */
637static inline void cris_update_result(DisasContext *dc, TCGv res)
638{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400639 if (dc->update_cc) {
640 tcg_gen_mov_tl(cc_result, res);
641 }
edgar_igl30abcfc2008-05-27 21:10:56 +0000642}
643
644/* Returns one if the write back stage should execute. */
645static void cris_alu_op_exec(DisasContext *dc, int op,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400646 TCGv dst, TCGv a, TCGv b, int size)
edgar_igl30abcfc2008-05-27 21:10:56 +0000647{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400648 /* Emit the ALU insns. */
649 switch (op) {
650 case CC_OP_ADD:
651 tcg_gen_add_tl(dst, a, b);
Michael Tokarev8b819682023-07-14 14:23:51 +0300652 /* Extended arithmetic. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400653 t_gen_addx_carry(dc, dst);
654 break;
655 case CC_OP_ADDC:
656 tcg_gen_add_tl(dst, a, b);
657 t_gen_add_flag(dst, 0); /* C_FLAG. */
658 break;
659 case CC_OP_MCP:
660 tcg_gen_add_tl(dst, a, b);
661 t_gen_add_flag(dst, 8); /* R_FLAG. */
662 break;
663 case CC_OP_SUB:
664 tcg_gen_sub_tl(dst, a, b);
Michael Tokarev8b819682023-07-14 14:23:51 +0300665 /* Extended arithmetic. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400666 t_gen_subx_carry(dc, dst);
667 break;
668 case CC_OP_MOVE:
669 tcg_gen_mov_tl(dst, b);
670 break;
671 case CC_OP_OR:
672 tcg_gen_or_tl(dst, a, b);
673 break;
674 case CC_OP_AND:
675 tcg_gen_and_tl(dst, a, b);
676 break;
677 case CC_OP_XOR:
678 tcg_gen_xor_tl(dst, a, b);
679 break;
680 case CC_OP_LSL:
681 t_gen_lsl(dst, a, b);
682 break;
683 case CC_OP_LSR:
684 t_gen_lsr(dst, a, b);
685 break;
686 case CC_OP_ASR:
687 t_gen_asr(dst, a, b);
688 break;
689 case CC_OP_NEG:
690 tcg_gen_neg_tl(dst, b);
Michael Tokarev8b819682023-07-14 14:23:51 +0300691 /* Extended arithmetic. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400692 t_gen_subx_carry(dc, dst);
693 break;
694 case CC_OP_LZ:
Richard Henderson272694a2016-11-16 10:54:57 +0100695 tcg_gen_clzi_tl(dst, b, TARGET_LONG_BITS);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400696 break;
697 case CC_OP_MULS:
Richard Hendersonbf45f972013-02-19 23:52:11 -0800698 tcg_gen_muls2_tl(dst, cpu_PR[PR_MOF], a, b);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400699 break;
700 case CC_OP_MULU:
Richard Hendersonbf45f972013-02-19 23:52:11 -0800701 tcg_gen_mulu2_tl(dst, cpu_PR[PR_MOF], a, b);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400702 break;
703 case CC_OP_DSTEP:
704 t_gen_cris_dstep(dst, a, b);
705 break;
706 case CC_OP_MSTEP:
707 t_gen_cris_mstep(dst, a, b, cpu_PR[PR_CCS]);
708 break;
709 case CC_OP_BOUND:
Richard Henderson88174012015-09-02 11:38:10 -0700710 tcg_gen_movcond_tl(TCG_COND_LEU, dst, a, b, a, b);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400711 break;
712 case CC_OP_CMP:
713 tcg_gen_sub_tl(dst, a, b);
Michael Tokarev8b819682023-07-14 14:23:51 +0300714 /* Extended arithmetic. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400715 t_gen_subx_carry(dc, dst);
716 break;
717 default:
Paolo Bonzini79e8ed32015-11-13 13:24:26 +0100718 qemu_log_mask(LOG_GUEST_ERROR, "illegal ALU op.\n");
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400719 BUG();
720 break;
721 }
ths81700282007-10-08 12:49:08 +0000722
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400723 if (size == 1) {
724 tcg_gen_andi_tl(dst, dst, 0xff);
725 } else if (size == 2) {
726 tcg_gen_andi_tl(dst, dst, 0xffff);
727 }
edgar_igl30abcfc2008-05-27 21:10:56 +0000728}
729
730static void cris_alu(DisasContext *dc, int op,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400731 TCGv d, TCGv op_a, TCGv op_b, int size)
edgar_igl30abcfc2008-05-27 21:10:56 +0000732{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400733 TCGv tmp;
734 int writeback;
edgar_igl30abcfc2008-05-27 21:10:56 +0000735
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400736 writeback = 1;
edgar_igl31c18d82008-10-27 20:24:59 +0000737
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400738 if (op == CC_OP_CMP) {
739 tmp = tcg_temp_new();
740 writeback = 0;
741 } else if (size == 4) {
742 tmp = d;
743 writeback = 0;
744 } else {
745 tmp = tcg_temp_new();
746 }
edgar_igl44696292008-10-28 00:13:15 +0000747
edgar_igl30abcfc2008-05-27 21:10:56 +0000748
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400749 cris_pre_alu_update_cc(dc, op, op_a, op_b, size);
750 cris_alu_op_exec(dc, op, tmp, op_a, op_b, size);
751 cris_update_result(dc, tmp);
edgar_igl05ba7d52008-03-14 01:11:25 +0000752
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400753 /* Writeback. */
754 if (writeback) {
755 if (size == 1) {
756 tcg_gen_andi_tl(d, d, ~0xff);
757 } else {
758 tcg_gen_andi_tl(d, d, ~0xffff);
759 }
760 tcg_gen_or_tl(d, d, tmp);
761 }
ths81700282007-10-08 12:49:08 +0000762}
763
764static int arith_cc(DisasContext *dc)
765{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400766 if (dc->update_cc) {
767 switch (dc->cc_op) {
768 case CC_OP_ADDC: return 1;
769 case CC_OP_ADD: return 1;
770 case CC_OP_SUB: return 1;
771 case CC_OP_DSTEP: return 1;
772 case CC_OP_LSL: return 1;
773 case CC_OP_LSR: return 1;
774 case CC_OP_ASR: return 1;
775 case CC_OP_CMP: return 1;
776 case CC_OP_NEG: return 1;
777 case CC_OP_OR: return 1;
778 case CC_OP_AND: return 1;
779 case CC_OP_XOR: return 1;
780 case CC_OP_MULU: return 1;
781 case CC_OP_MULS: return 1;
782 default:
783 return 0;
784 }
785 }
786 return 0;
ths81700282007-10-08 12:49:08 +0000787}
788
edgar_iglc5631f42008-10-27 13:52:44 +0000789static void gen_tst_cc (DisasContext *dc, TCGv cc, int cond)
ths81700282007-10-08 12:49:08 +0000790{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400791 int arith_opt, move_opt;
ths81700282007-10-08 12:49:08 +0000792
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400793 /* TODO: optimize more condition codes. */
edgar_igldceaf392008-05-07 15:24:53 +0000794
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400795 /*
796 * If the flags are live, we've gotta look into the bits of CCS.
797 * Otherwise, if we just did an arithmetic operation we try to
798 * evaluate the condition code faster.
799 *
800 * When this function is done, T0 should be non-zero if the condition
801 * code is true.
802 */
803 arith_opt = arith_cc(dc) && !dc->flags_uptodate;
804 move_opt = (dc->cc_op == CC_OP_MOVE);
805 switch (cond) {
806 case CC_EQ:
807 if ((arith_opt || move_opt)
808 && dc->cc_x_uptodate != (2 | X_FLAG)) {
Stefan Sandstromfd52dee2021-02-19 13:44:16 +0100809 tcg_gen_setcondi_tl(TCG_COND_EQ, cc, cc_result, 0);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400810 } else {
811 cris_evaluate_flags(dc);
812 tcg_gen_andi_tl(cc,
813 cpu_PR[PR_CCS], Z_FLAG);
814 }
815 break;
816 case CC_NE:
817 if ((arith_opt || move_opt)
818 && dc->cc_x_uptodate != (2 | X_FLAG)) {
819 tcg_gen_mov_tl(cc, cc_result);
820 } else {
821 cris_evaluate_flags(dc);
822 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
823 Z_FLAG);
824 tcg_gen_andi_tl(cc, cc, Z_FLAG);
825 }
826 break;
827 case CC_CS:
828 cris_evaluate_flags(dc);
829 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], C_FLAG);
830 break;
831 case CC_CC:
832 cris_evaluate_flags(dc);
833 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS], C_FLAG);
834 tcg_gen_andi_tl(cc, cc, C_FLAG);
835 break;
836 case CC_VS:
837 cris_evaluate_flags(dc);
838 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], V_FLAG);
839 break;
840 case CC_VC:
841 cris_evaluate_flags(dc);
842 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
843 V_FLAG);
844 tcg_gen_andi_tl(cc, cc, V_FLAG);
845 break;
846 case CC_PL:
847 if (arith_opt || move_opt) {
848 int bits = 31;
edgar_igl2a44f7f2008-06-06 11:23:28 +0000849
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400850 if (dc->cc_size == 1) {
851 bits = 7;
852 } else if (dc->cc_size == 2) {
853 bits = 15;
854 }
edgar_igl2a44f7f2008-06-06 11:23:28 +0000855
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400856 tcg_gen_shri_tl(cc, cc_result, bits);
857 tcg_gen_xori_tl(cc, cc, 1);
858 } else {
859 cris_evaluate_flags(dc);
860 tcg_gen_xori_tl(cc, cpu_PR[PR_CCS],
861 N_FLAG);
862 tcg_gen_andi_tl(cc, cc, N_FLAG);
863 }
864 break;
865 case CC_MI:
866 if (arith_opt || move_opt) {
867 int bits = 31;
edgar_igl2a44f7f2008-06-06 11:23:28 +0000868
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400869 if (dc->cc_size == 1) {
870 bits = 7;
871 } else if (dc->cc_size == 2) {
872 bits = 15;
873 }
edgar_igl2a44f7f2008-06-06 11:23:28 +0000874
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400875 tcg_gen_shri_tl(cc, cc_result, bits);
876 tcg_gen_andi_tl(cc, cc, 1);
877 } else {
878 cris_evaluate_flags(dc);
879 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
880 N_FLAG);
881 }
882 break;
883 case CC_LS:
884 cris_evaluate_flags(dc);
885 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS],
886 C_FLAG | Z_FLAG);
887 break;
888 case CC_HI:
889 cris_evaluate_flags(dc);
890 {
891 TCGv tmp;
edgar_igldceaf392008-05-07 15:24:53 +0000892
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400893 tmp = tcg_temp_new();
894 tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS],
895 C_FLAG | Z_FLAG);
896 /* Overlay the C flag on top of the Z. */
897 tcg_gen_shli_tl(cc, tmp, 2);
898 tcg_gen_and_tl(cc, tmp, cc);
899 tcg_gen_andi_tl(cc, cc, Z_FLAG);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400900 }
901 break;
902 case CC_GE:
903 cris_evaluate_flags(dc);
904 /* Overlay the V flag on top of the N. */
905 tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
906 tcg_gen_xor_tl(cc,
907 cpu_PR[PR_CCS], cc);
908 tcg_gen_andi_tl(cc, cc, N_FLAG);
909 tcg_gen_xori_tl(cc, cc, N_FLAG);
910 break;
911 case CC_LT:
912 cris_evaluate_flags(dc);
913 /* Overlay the V flag on top of the N. */
914 tcg_gen_shli_tl(cc, cpu_PR[PR_CCS], 2);
915 tcg_gen_xor_tl(cc,
916 cpu_PR[PR_CCS], cc);
917 tcg_gen_andi_tl(cc, cc, N_FLAG);
918 break;
919 case CC_GT:
920 cris_evaluate_flags(dc);
921 {
922 TCGv n, z;
edgar_igldceaf392008-05-07 15:24:53 +0000923
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400924 n = tcg_temp_new();
925 z = tcg_temp_new();
edgar_igldceaf392008-05-07 15:24:53 +0000926
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400927 /* To avoid a shift we overlay everything on
928 the V flag. */
929 tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
930 tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
931 /* invert Z. */
932 tcg_gen_xori_tl(z, z, 2);
edgar_igldceaf392008-05-07 15:24:53 +0000933
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400934 tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
935 tcg_gen_xori_tl(n, n, 2);
936 tcg_gen_and_tl(cc, z, n);
937 tcg_gen_andi_tl(cc, cc, 2);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400938 }
939 break;
940 case CC_LE:
941 cris_evaluate_flags(dc);
942 {
943 TCGv n, z;
edgar_igldceaf392008-05-07 15:24:53 +0000944
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400945 n = tcg_temp_new();
946 z = tcg_temp_new();
edgar_igldceaf392008-05-07 15:24:53 +0000947
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400948 /* To avoid a shift we overlay everything on
949 the V flag. */
950 tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2);
951 tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1);
edgar_igldceaf392008-05-07 15:24:53 +0000952
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400953 tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]);
954 tcg_gen_or_tl(cc, z, n);
955 tcg_gen_andi_tl(cc, cc, 2);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400956 }
957 break;
958 case CC_P:
959 cris_evaluate_flags(dc);
960 tcg_gen_andi_tl(cc, cpu_PR[PR_CCS], P_FLAG);
961 break;
962 case CC_A:
963 tcg_gen_movi_tl(cc, 1);
964 break;
965 default:
966 BUG();
967 break;
968 };
ths81700282007-10-08 12:49:08 +0000969}
970
edgar_igl2a44f7f2008-06-06 11:23:28 +0000971static void cris_store_direct_jmp(DisasContext *dc)
972{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400973 /* Store the direct jmp state into the cpu-state. */
974 if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
975 if (dc->jmp == JMP_DIRECT) {
976 tcg_gen_movi_tl(env_btaken, 1);
977 }
978 tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
979 dc->jmp = JMP_INDIRECT;
980 }
edgar_igl2a44f7f2008-06-06 11:23:28 +0000981}
982
983static void cris_prepare_cc_branch (DisasContext *dc,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400984 int offset, int cond)
ths81700282007-10-08 12:49:08 +0000985{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400986 /* This helps us re-schedule the micro-code to insns in delay-slots
987 before the actual jump. */
988 dc->delayed_branch = 2;
989 dc->jmp = JMP_DIRECT_CC;
990 dc->jmp_pc = dc->pc + offset;
edgar_igl2a44f7f2008-06-06 11:23:28 +0000991
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +0400992 gen_tst_cc(dc, env_btaken, cond);
993 tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
ths81700282007-10-08 12:49:08 +0000994}
995
edgar_iglb41f7df2008-05-02 22:16:17 +0000996
edgar_igl2a44f7f2008-06-06 11:23:28 +0000997/* jumps, when the dest is in a live reg for example. Direct should be set
998 when the dest addr is constant to allow tb chaining. */
999static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
ths81700282007-10-08 12:49:08 +00001000{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001001 /* This helps us re-schedule the micro-code to insns in delay-slots
1002 before the actual jump. */
1003 dc->delayed_branch = 2;
1004 dc->jmp = type;
1005 if (type == JMP_INDIRECT) {
1006 tcg_gen_movi_tl(env_btaken, 1);
1007 }
ths81700282007-10-08 12:49:08 +00001008}
1009
pbrooka7812ae2008-11-17 14:43:54 +00001010static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
1011{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001012 /* If we get a fault on a delayslot we must keep the jmp state in
1013 the cpu-state to be able to re-execute the jmp. */
1014 if (dc->delayed_branch == 1) {
1015 cris_store_direct_jmp(dc);
1016 }
pbrooka7812ae2008-11-17 14:43:54 +00001017
Richard Henderson97fc0c22024-01-28 15:05:06 +10001018 tcg_gen_qemu_ld_i64(dst, addr, dc->mem_index, MO_TEUQ);
pbrooka7812ae2008-11-17 14:43:54 +00001019}
1020
edgar_igl9b32fbf2008-10-07 22:54:52 +00001021static void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001022 unsigned int size, int sign)
ths81700282007-10-08 12:49:08 +00001023{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001024 /* If we get a fault on a delayslot we must keep the jmp state in
1025 the cpu-state to be able to re-execute the jmp. */
1026 if (dc->delayed_branch == 1) {
1027 cris_store_direct_jmp(dc);
1028 }
edgar_igl2a44f7f2008-06-06 11:23:28 +00001029
Richard Henderson97fc0c22024-01-28 15:05:06 +10001030 tcg_gen_qemu_ld_tl(dst, addr, dc->mem_index,
Richard Hendersona1d22a32013-12-07 14:52:34 +13001031 MO_TE + ctz32(size) + (sign ? MO_SIGN : 0));
ths81700282007-10-08 12:49:08 +00001032}
1033
edgar_igl9b32fbf2008-10-07 22:54:52 +00001034static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001035 unsigned int size)
ths81700282007-10-08 12:49:08 +00001036{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001037 /* If we get a fault on a delayslot we must keep the jmp state in
1038 the cpu-state to be able to re-execute the jmp. */
1039 if (dc->delayed_branch == 1) {
1040 cris_store_direct_jmp(dc);
1041 }
edgar_igl2a44f7f2008-06-06 11:23:28 +00001042
1043
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001044 /* Conditional writes. We only support the kind were X and P are known
1045 at translation time. */
Richard Henderson0ce97a32021-06-22 08:18:12 -07001046 if (dc->flags_x && (dc->tb_flags & P_FLAG)) {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001047 dc->postinc = 0;
1048 cris_evaluate_flags(dc);
1049 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], C_FLAG);
1050 return;
1051 }
edgar_igl2a44f7f2008-06-06 11:23:28 +00001052
Richard Henderson97fc0c22024-01-28 15:05:06 +10001053 tcg_gen_qemu_st_tl(val, addr, dc->mem_index, MO_TE + ctz32(size));
edgar_igl2a44f7f2008-06-06 11:23:28 +00001054
Richard Henderson0ce97a32021-06-22 08:18:12 -07001055 if (dc->flags_x) {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001056 cris_evaluate_flags(dc);
1057 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~C_FLAG);
1058 }
ths81700282007-10-08 12:49:08 +00001059}
1060
edgar_igl05ba7d52008-03-14 01:11:25 +00001061static inline void t_gen_sext(TCGv d, TCGv s, int size)
ths81700282007-10-08 12:49:08 +00001062{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001063 if (size == 1) {
1064 tcg_gen_ext8s_i32(d, s);
1065 } else if (size == 2) {
1066 tcg_gen_ext16s_i32(d, s);
Richard Henderson11f4e8f2017-10-19 20:27:27 -07001067 } else {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001068 tcg_gen_mov_tl(d, s);
1069 }
ths81700282007-10-08 12:49:08 +00001070}
1071
edgar_igl05ba7d52008-03-14 01:11:25 +00001072static inline void t_gen_zext(TCGv d, TCGv s, int size)
ths81700282007-10-08 12:49:08 +00001073{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001074 if (size == 1) {
1075 tcg_gen_ext8u_i32(d, s);
1076 } else if (size == 2) {
1077 tcg_gen_ext16u_i32(d, s);
Richard Henderson11f4e8f2017-10-19 20:27:27 -07001078 } else {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001079 tcg_gen_mov_tl(d, s);
1080 }
ths81700282007-10-08 12:49:08 +00001081}
1082
1083#if DISAS_CRIS
1084static char memsize_char(int size)
1085{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001086 switch (size) {
Liao Pingfang8ff1e462020-07-13 17:05:50 +08001087 case 1: return 'b';
1088 case 2: return 'w';
1089 case 4: return 'd';
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001090 default:
1091 return 'x';
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001092 }
ths81700282007-10-08 12:49:08 +00001093}
1094#endif
1095
edgar_igl30abcfc2008-05-27 21:10:56 +00001096static inline unsigned int memsize_z(DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001097{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001098 return dc->zsize + 1;
ths81700282007-10-08 12:49:08 +00001099}
1100
edgar_igl30abcfc2008-05-27 21:10:56 +00001101static inline unsigned int memsize_zz(DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001102{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001103 switch (dc->zzsize) {
1104 case 0: return 1;
1105 case 1: return 2;
1106 default:
1107 return 4;
1108 }
ths81700282007-10-08 12:49:08 +00001109}
1110
edgar_iglc7d05692008-05-03 06:54:52 +00001111static inline void do_postinc (DisasContext *dc, int size)
ths81700282007-10-08 12:49:08 +00001112{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001113 if (dc->postinc) {
1114 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], size);
1115 }
ths81700282007-10-08 12:49:08 +00001116}
1117
edgar_igl30abcfc2008-05-27 21:10:56 +00001118static inline void dec_prep_move_r(DisasContext *dc, int rs, int rd,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001119 int size, int s_ext, TCGv dst)
ths81700282007-10-08 12:49:08 +00001120{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001121 if (s_ext) {
1122 t_gen_sext(dst, cpu_R[rs], size);
1123 } else {
1124 t_gen_zext(dst, cpu_R[rs], size);
1125 }
ths81700282007-10-08 12:49:08 +00001126}
1127
1128/* Prepare T0 and T1 for a register alu operation.
1129 s_ext decides if the operand1 should be sign-extended or zero-extended when
1130 needed. */
1131static void dec_prep_alu_r(DisasContext *dc, int rs, int rd,
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001132 int size, int s_ext, TCGv dst, TCGv src)
ths81700282007-10-08 12:49:08 +00001133{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001134 dec_prep_move_r(dc, rs, rd, size, s_ext, src);
ths81700282007-10-08 12:49:08 +00001135
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001136 if (s_ext) {
1137 t_gen_sext(dst, cpu_R[rd], size);
1138 } else {
1139 t_gen_zext(dst, cpu_R[rd], size);
1140 }
ths81700282007-10-08 12:49:08 +00001141}
1142
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001143static int dec_prep_move_m(CPUCRISState *env, DisasContext *dc,
1144 int s_ext, int memsize, TCGv dst)
ths81700282007-10-08 12:49:08 +00001145{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001146 unsigned int rs;
1147 uint32_t imm;
1148 int is_imm;
1149 int insn_len = 2;
ths81700282007-10-08 12:49:08 +00001150
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001151 rs = dc->op1;
1152 is_imm = rs == 15 && dc->postinc;
ths81700282007-10-08 12:49:08 +00001153
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001154 /* Load [$rs] onto T1. */
1155 if (is_imm) {
1156 insn_len = 2 + memsize;
1157 if (memsize == 1) {
1158 insn_len++;
1159 }
ths81700282007-10-08 12:49:08 +00001160
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001161 imm = cris_fetch(env, dc, dc->pc + 2, memsize, s_ext);
1162 tcg_gen_movi_tl(dst, imm);
1163 dc->postinc = 0;
1164 } else {
1165 cris_flush_cc_state(dc);
1166 gen_load(dc, dst, cpu_R[rs], memsize, 0);
1167 if (s_ext) {
1168 t_gen_sext(dst, dst, memsize);
1169 } else {
1170 t_gen_zext(dst, dst, memsize);
1171 }
1172 }
1173 return insn_len;
edgar_iglcf1d97f2008-05-13 10:59:14 +00001174}
1175
1176/* Prepare T0 and T1 for a memory + alu operation.
1177 s_ext decides if the operand1 should be sign-extended or zero-extended when
1178 needed. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001179static int dec_prep_alu_m(CPUCRISState *env, DisasContext *dc,
1180 int s_ext, int memsize, TCGv dst, TCGv src)
edgar_iglcf1d97f2008-05-13 10:59:14 +00001181{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001182 int insn_len;
edgar_iglcf1d97f2008-05-13 10:59:14 +00001183
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001184 insn_len = dec_prep_move_m(env, dc, s_ext, memsize, src);
1185 tcg_gen_mov_tl(dst, cpu_R[dc->op2]);
1186 return insn_len;
ths81700282007-10-08 12:49:08 +00001187}
1188
1189#if DISAS_CRIS
1190static const char *cc_name(int cc)
1191{
Richard Henderson5899ce62021-06-19 20:57:31 -07001192 static const char * const cc_names[16] = {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001193 "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi",
1194 "ls", "hi", "ge", "lt", "gt", "le", "a", "p"
1195 };
1196 assert(cc < 16);
1197 return cc_names[cc];
ths81700282007-10-08 12:49:08 +00001198}
1199#endif
1200
edgar_iglb41f7df2008-05-02 22:16:17 +00001201/* Start of insn decoders. */
1202
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001203static int dec_bccq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001204{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001205 int32_t offset;
1206 int sign;
1207 uint32_t cond = dc->op2;
ths81700282007-10-08 12:49:08 +00001208
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001209 offset = EXTRACT_FIELD(dc->ir, 1, 7);
1210 sign = EXTRACT_FIELD(dc->ir, 0, 0);
ths81700282007-10-08 12:49:08 +00001211
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001212 offset *= 2;
1213 offset |= sign << 8;
1214 offset = sign_extend(offset, 8);
ths81700282007-10-08 12:49:08 +00001215
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001216 LOG_DIS("b%s %x\n", cc_name(cond), dc->pc + offset);
edgar_igl2a44f7f2008-06-06 11:23:28 +00001217
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001218 /* op2 holds the condition-code. */
1219 cris_cc_mask(dc, 0);
1220 cris_prepare_cc_branch(dc, offset, cond);
1221 return 2;
ths81700282007-10-08 12:49:08 +00001222}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001223static int dec_addoq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001224{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001225 int32_t imm;
ths81700282007-10-08 12:49:08 +00001226
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001227 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 7);
1228 imm = sign_extend(dc->op1, 7);
ths81700282007-10-08 12:49:08 +00001229
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001230 LOG_DIS("addoq %d, $r%u\n", imm, dc->op2);
1231 cris_cc_mask(dc, 0);
1232 /* Fetch register operand, */
1233 tcg_gen_addi_tl(cpu_R[R_ACR], cpu_R[dc->op2], imm);
edgar_iglfb48f712008-10-27 16:46:29 +00001234
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001235 return 2;
ths81700282007-10-08 12:49:08 +00001236}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001237static int dec_addq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001238{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001239 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001240 LOG_DIS("addq %u, $r%u\n", dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001241
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001242 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
ths81700282007-10-08 12:49:08 +00001243
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001244 cris_cc_mask(dc, CC_MASK_NZVC);
edgar_igl30abcfc2008-05-27 21:10:56 +00001245
Richard Hendersonab554f12023-02-25 12:44:04 -10001246 c = tcg_constant_tl(dc->op1);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001247 cris_alu(dc, CC_OP_ADD,
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001248 cpu_R[dc->op2], cpu_R[dc->op2], c, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001249 return 2;
ths81700282007-10-08 12:49:08 +00001250}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001251static int dec_moveq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001252{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001253 uint32_t imm;
ths81700282007-10-08 12:49:08 +00001254
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001255 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1256 imm = sign_extend(dc->op1, 5);
1257 LOG_DIS("moveq %d, $r%u\n", imm, dc->op2);
ths81700282007-10-08 12:49:08 +00001258
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001259 tcg_gen_movi_tl(cpu_R[dc->op2], imm);
1260 return 2;
ths81700282007-10-08 12:49:08 +00001261}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001262static int dec_subq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001263{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001264 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001265 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
ths81700282007-10-08 12:49:08 +00001266
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001267 LOG_DIS("subq %u, $r%u\n", dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001268
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001269 cris_cc_mask(dc, CC_MASK_NZVC);
Richard Hendersonab554f12023-02-25 12:44:04 -10001270 c = tcg_constant_tl(dc->op1);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001271 cris_alu(dc, CC_OP_SUB,
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001272 cpu_R[dc->op2], cpu_R[dc->op2], c, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001273 return 2;
ths81700282007-10-08 12:49:08 +00001274}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001275static int dec_cmpq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001276{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001277 uint32_t imm;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001278 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001279 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1280 imm = sign_extend(dc->op1, 5);
ths81700282007-10-08 12:49:08 +00001281
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001282 LOG_DIS("cmpq %d, $r%d\n", imm, dc->op2);
1283 cris_cc_mask(dc, CC_MASK_NZVC);
edgar_igl30abcfc2008-05-27 21:10:56 +00001284
Richard Hendersonab554f12023-02-25 12:44:04 -10001285 c = tcg_constant_tl(imm);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001286 cris_alu(dc, CC_OP_CMP,
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001287 cpu_R[dc->op2], cpu_R[dc->op2], c, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001288 return 2;
ths81700282007-10-08 12:49:08 +00001289}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001290static int dec_andq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001291{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001292 uint32_t imm;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001293 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001294 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1295 imm = sign_extend(dc->op1, 5);
ths81700282007-10-08 12:49:08 +00001296
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001297 LOG_DIS("andq %d, $r%d\n", imm, dc->op2);
1298 cris_cc_mask(dc, CC_MASK_NZ);
edgar_igl30abcfc2008-05-27 21:10:56 +00001299
Richard Hendersonab554f12023-02-25 12:44:04 -10001300 c = tcg_constant_tl(imm);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001301 cris_alu(dc, CC_OP_AND,
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001302 cpu_R[dc->op2], cpu_R[dc->op2], c, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001303 return 2;
ths81700282007-10-08 12:49:08 +00001304}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001305static int dec_orq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001306{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001307 uint32_t imm;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001308 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001309 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 5);
1310 imm = sign_extend(dc->op1, 5);
1311 LOG_DIS("orq %d, $r%d\n", imm, dc->op2);
1312 cris_cc_mask(dc, CC_MASK_NZ);
edgar_igl30abcfc2008-05-27 21:10:56 +00001313
Richard Hendersonab554f12023-02-25 12:44:04 -10001314 c = tcg_constant_tl(imm);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001315 cris_alu(dc, CC_OP_OR,
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001316 cpu_R[dc->op2], cpu_R[dc->op2], c, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001317 return 2;
ths81700282007-10-08 12:49:08 +00001318}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001319static int dec_btstq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001320{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001321 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001322 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1323 LOG_DIS("btstq %u, $r%d\n", dc->op1, dc->op2);
edgar_igl17ac9752008-05-06 08:30:15 +00001324
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001325 cris_cc_mask(dc, CC_MASK_NZ);
Richard Hendersonab554f12023-02-25 12:44:04 -10001326 c = tcg_constant_tl(dc->op1);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001327 cris_evaluate_flags(dc);
Richard Hendersonad75a512023-09-13 16:37:36 -07001328 gen_helper_btst(cpu_PR[PR_CCS], tcg_env, cpu_R[dc->op2],
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001329 c, cpu_PR[PR_CCS]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001330 cris_alu(dc, CC_OP_MOVE,
1331 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
1332 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
1333 dc->flags_uptodate = 1;
1334 return 2;
ths81700282007-10-08 12:49:08 +00001335}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001336static int dec_asrq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001337{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001338 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1339 LOG_DIS("asrq %u, $r%d\n", dc->op1, dc->op2);
1340 cris_cc_mask(dc, CC_MASK_NZ);
edgar_igl30abcfc2008-05-27 21:10:56 +00001341
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001342 tcg_gen_sari_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1343 cris_alu(dc, CC_OP_MOVE,
1344 cpu_R[dc->op2],
1345 cpu_R[dc->op2], cpu_R[dc->op2], 4);
1346 return 2;
ths81700282007-10-08 12:49:08 +00001347}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001348static int dec_lslq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001349{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001350 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1351 LOG_DIS("lslq %u, $r%d\n", dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001352
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001353 cris_cc_mask(dc, CC_MASK_NZ);
edgar_igl30abcfc2008-05-27 21:10:56 +00001354
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001355 tcg_gen_shli_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
edgar_igl2a44f7f2008-06-06 11:23:28 +00001356
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001357 cris_alu(dc, CC_OP_MOVE,
1358 cpu_R[dc->op2],
1359 cpu_R[dc->op2], cpu_R[dc->op2], 4);
1360 return 2;
ths81700282007-10-08 12:49:08 +00001361}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001362static int dec_lsrq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001363{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001364 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
1365 LOG_DIS("lsrq %u, $r%d\n", dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001366
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001367 cris_cc_mask(dc, CC_MASK_NZ);
edgar_igl30abcfc2008-05-27 21:10:56 +00001368
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001369 tcg_gen_shri_tl(cpu_R[dc->op2], cpu_R[dc->op2], dc->op1);
1370 cris_alu(dc, CC_OP_MOVE,
1371 cpu_R[dc->op2],
1372 cpu_R[dc->op2], cpu_R[dc->op2], 4);
1373 return 2;
ths81700282007-10-08 12:49:08 +00001374}
1375
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001376static int dec_move_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001377{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001378 int size = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00001379
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001380 LOG_DIS("move.%c $r%u, $r%u\n",
1381 memsize_char(size), dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001382
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001383 cris_cc_mask(dc, CC_MASK_NZ);
1384 if (size == 4) {
1385 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, cpu_R[dc->op2]);
1386 cris_cc_mask(dc, CC_MASK_NZ);
1387 cris_update_cc_op(dc, CC_OP_MOVE, 4);
1388 cris_update_cc_x(dc);
1389 cris_update_result(dc, cpu_R[dc->op2]);
1390 } else {
1391 TCGv t0;
edgar_igl43d7ac42008-10-27 13:55:28 +00001392
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001393 t0 = tcg_temp_new();
1394 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
1395 cris_alu(dc, CC_OP_MOVE,
1396 cpu_R[dc->op2],
1397 cpu_R[dc->op2], t0, size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001398 }
1399 return 2;
ths81700282007-10-08 12:49:08 +00001400}
1401
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001402static int dec_scc_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001403{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001404 int cond = dc->op2;
ths81700282007-10-08 12:49:08 +00001405
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001406 LOG_DIS("s%s $r%u\n",
1407 cc_name(cond), dc->op1);
ths81700282007-10-08 12:49:08 +00001408
Richard Henderson88174012015-09-02 11:38:10 -07001409 gen_tst_cc(dc, cpu_R[dc->op1], cond);
1410 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_R[dc->op1], cpu_R[dc->op1], 0);
ths81700282007-10-08 12:49:08 +00001411
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001412 cris_cc_mask(dc, 0);
1413 return 2;
ths81700282007-10-08 12:49:08 +00001414}
1415
edgar_iglfb48f712008-10-27 16:46:29 +00001416static inline void cris_alu_alloc_temps(DisasContext *dc, int size, TCGv *t)
1417{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001418 if (size == 4) {
1419 t[0] = cpu_R[dc->op2];
1420 t[1] = cpu_R[dc->op1];
1421 } else {
1422 t[0] = tcg_temp_new();
1423 t[1] = tcg_temp_new();
1424 }
edgar_iglfb48f712008-10-27 16:46:29 +00001425}
1426
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001427static int dec_and_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001428{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001429 TCGv t[2];
1430 int size = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00001431
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001432 LOG_DIS("and.%c $r%u, $r%u\n",
1433 memsize_char(size), dc->op1, dc->op2);
edgar_igl30abcfc2008-05-27 21:10:56 +00001434
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001435 cris_cc_mask(dc, CC_MASK_NZ);
edgar_iglfb48f712008-10-27 16:46:29 +00001436
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001437 cris_alu_alloc_temps(dc, size, t);
1438 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1439 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001440 return 2;
ths81700282007-10-08 12:49:08 +00001441}
1442
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001443static int dec_lz_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001444{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001445 TCGv t0;
1446 LOG_DIS("lz $r%u, $r%u\n",
1447 dc->op1, dc->op2);
1448 cris_cc_mask(dc, CC_MASK_NZ);
1449 t0 = tcg_temp_new();
1450 dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0, cpu_R[dc->op2], t0);
1451 cris_alu(dc, CC_OP_LZ, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001452 return 2;
ths81700282007-10-08 12:49:08 +00001453}
1454
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001455static int dec_lsl_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001456{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001457 TCGv t[2];
1458 int size = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00001459
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001460 LOG_DIS("lsl.%c $r%u, $r%u\n",
1461 memsize_char(size), dc->op1, dc->op2);
edgar_igl30abcfc2008-05-27 21:10:56 +00001462
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001463 cris_cc_mask(dc, CC_MASK_NZ);
1464 cris_alu_alloc_temps(dc, size, t);
1465 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1466 tcg_gen_andi_tl(t[1], t[1], 63);
1467 cris_alu(dc, CC_OP_LSL, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001468 return 2;
ths81700282007-10-08 12:49:08 +00001469}
1470
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001471static int dec_lsr_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001472{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001473 TCGv t[2];
1474 int size = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00001475
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001476 LOG_DIS("lsr.%c $r%u, $r%u\n",
1477 memsize_char(size), dc->op1, dc->op2);
edgar_igl30abcfc2008-05-27 21:10:56 +00001478
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001479 cris_cc_mask(dc, CC_MASK_NZ);
1480 cris_alu_alloc_temps(dc, size, t);
1481 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1482 tcg_gen_andi_tl(t[1], t[1], 63);
1483 cris_alu(dc, CC_OP_LSR, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001484 return 2;
ths81700282007-10-08 12:49:08 +00001485}
1486
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001487static int dec_asr_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001488{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001489 TCGv t[2];
1490 int size = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00001491
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001492 LOG_DIS("asr.%c $r%u, $r%u\n",
1493 memsize_char(size), dc->op1, dc->op2);
edgar_igl30abcfc2008-05-27 21:10:56 +00001494
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001495 cris_cc_mask(dc, CC_MASK_NZ);
1496 cris_alu_alloc_temps(dc, size, t);
1497 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
1498 tcg_gen_andi_tl(t[1], t[1], 63);
1499 cris_alu(dc, CC_OP_ASR, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001500 return 2;
ths81700282007-10-08 12:49:08 +00001501}
1502
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001503static int dec_muls_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001504{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001505 TCGv t[2];
1506 int size = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00001507
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001508 LOG_DIS("muls.%c $r%u, $r%u\n",
1509 memsize_char(size), dc->op1, dc->op2);
1510 cris_cc_mask(dc, CC_MASK_NZV);
1511 cris_alu_alloc_temps(dc, size, t);
1512 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 1, t[0], t[1]);
edgar_igl30abcfc2008-05-27 21:10:56 +00001513
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001514 cris_alu(dc, CC_OP_MULS, cpu_R[dc->op2], t[0], t[1], 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001515 return 2;
ths81700282007-10-08 12:49:08 +00001516}
1517
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001518static int dec_mulu_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001519{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001520 TCGv t[2];
1521 int size = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00001522
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001523 LOG_DIS("mulu.%c $r%u, $r%u\n",
1524 memsize_char(size), dc->op1, dc->op2);
1525 cris_cc_mask(dc, CC_MASK_NZV);
1526 cris_alu_alloc_temps(dc, size, t);
1527 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
edgar_igl30abcfc2008-05-27 21:10:56 +00001528
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001529 cris_alu(dc, CC_OP_MULU, cpu_R[dc->op2], t[0], t[1], 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001530 return 2;
ths81700282007-10-08 12:49:08 +00001531}
1532
1533
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001534static int dec_dstep_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001535{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001536 LOG_DIS("dstep $r%u, $r%u\n", dc->op1, dc->op2);
1537 cris_cc_mask(dc, CC_MASK_NZ);
1538 cris_alu(dc, CC_OP_DSTEP,
1539 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
1540 return 2;
ths81700282007-10-08 12:49:08 +00001541}
1542
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001543static int dec_xor_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001544{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001545 TCGv t[2];
1546 int size = memsize_zz(dc);
1547 LOG_DIS("xor.%c $r%u, $r%u\n",
1548 memsize_char(size), dc->op1, dc->op2);
1549 BUG_ON(size != 4); /* xor is dword. */
1550 cris_cc_mask(dc, CC_MASK_NZ);
1551 cris_alu_alloc_temps(dc, size, t);
1552 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
edgar_igl30abcfc2008-05-27 21:10:56 +00001553
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001554 cris_alu(dc, CC_OP_XOR, cpu_R[dc->op2], t[0], t[1], 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001555 return 2;
ths81700282007-10-08 12:49:08 +00001556}
1557
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001558static int dec_bound_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001559{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001560 TCGv l0;
1561 int size = memsize_zz(dc);
1562 LOG_DIS("bound.%c $r%u, $r%u\n",
1563 memsize_char(size), dc->op1, dc->op2);
1564 cris_cc_mask(dc, CC_MASK_NZ);
Richard Henderson5f153b12023-01-29 14:40:21 -10001565 l0 = tcg_temp_new();
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001566 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, l0);
1567 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], cpu_R[dc->op2], l0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001568 return 2;
ths81700282007-10-08 12:49:08 +00001569}
1570
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001571static int dec_cmp_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001572{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001573 TCGv t[2];
1574 int size = memsize_zz(dc);
1575 LOG_DIS("cmp.%c $r%u, $r%u\n",
1576 memsize_char(size), dc->op1, dc->op2);
1577 cris_cc_mask(dc, CC_MASK_NZVC);
1578 cris_alu_alloc_temps(dc, size, t);
1579 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
edgar_igl30abcfc2008-05-27 21:10:56 +00001580
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001581 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001582 return 2;
ths81700282007-10-08 12:49:08 +00001583}
1584
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001585static int dec_abs_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001586{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001587 LOG_DIS("abs $r%u, $r%u\n",
1588 dc->op1, dc->op2);
1589 cris_cc_mask(dc, CC_MASK_NZ);
edgar_igl3157a0a2008-03-15 20:45:05 +00001590
Richard Henderson73f671f2019-04-17 14:32:37 -10001591 tcg_gen_abs_tl(cpu_R[dc->op2], cpu_R[dc->op1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001592 cris_alu(dc, CC_OP_MOVE,
1593 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
1594 return 2;
ths81700282007-10-08 12:49:08 +00001595}
1596
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001597static int dec_add_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001598{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001599 TCGv t[2];
1600 int size = memsize_zz(dc);
1601 LOG_DIS("add.%c $r%u, $r%u\n",
1602 memsize_char(size), dc->op1, dc->op2);
1603 cris_cc_mask(dc, CC_MASK_NZVC);
1604 cris_alu_alloc_temps(dc, size, t);
1605 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
edgar_igl30abcfc2008-05-27 21:10:56 +00001606
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001607 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001608 return 2;
ths81700282007-10-08 12:49:08 +00001609}
1610
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001611static int dec_addc_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001612{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001613 LOG_DIS("addc $r%u, $r%u\n",
1614 dc->op1, dc->op2);
1615 cris_evaluate_flags(dc);
Richard Henderson0ce97a32021-06-22 08:18:12 -07001616
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001617 /* Set for this insn. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001618 dc->flags_x = X_FLAG;
edgar_igla8cf66b2009-01-07 12:25:15 +00001619
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001620 cris_cc_mask(dc, CC_MASK_NZVC);
1621 cris_alu(dc, CC_OP_ADDC,
1622 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
1623 return 2;
ths81700282007-10-08 12:49:08 +00001624}
1625
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001626static int dec_mcp_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001627{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001628 LOG_DIS("mcp $p%u, $r%u\n",
1629 dc->op2, dc->op1);
1630 cris_evaluate_flags(dc);
1631 cris_cc_mask(dc, CC_MASK_RNZV);
1632 cris_alu(dc, CC_OP_MCP,
1633 cpu_R[dc->op1], cpu_R[dc->op1], cpu_PR[dc->op2], 4);
1634 return 2;
ths81700282007-10-08 12:49:08 +00001635}
1636
1637#if DISAS_CRIS
1638static char * swapmode_name(int mode, char *modename) {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001639 int i = 0;
1640 if (mode & 8) {
1641 modename[i++] = 'n';
1642 }
1643 if (mode & 4) {
1644 modename[i++] = 'w';
1645 }
1646 if (mode & 2) {
1647 modename[i++] = 'b';
1648 }
1649 if (mode & 1) {
1650 modename[i++] = 'r';
1651 }
1652 modename[i++] = 0;
1653 return modename;
ths81700282007-10-08 12:49:08 +00001654}
1655#endif
1656
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001657static int dec_swap_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001658{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001659 TCGv t0;
edgar_iglcf1d97f2008-05-13 10:59:14 +00001660#if DISAS_CRIS
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001661 char modename[4];
edgar_iglcf1d97f2008-05-13 10:59:14 +00001662#endif
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001663 LOG_DIS("swap%s $r%u\n",
1664 swapmode_name(dc->op2, modename), dc->op1);
ths81700282007-10-08 12:49:08 +00001665
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001666 cris_cc_mask(dc, CC_MASK_NZ);
1667 t0 = tcg_temp_new();
Peter Maydell08397c42014-06-07 18:03:01 +01001668 tcg_gen_mov_tl(t0, cpu_R[dc->op1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001669 if (dc->op2 & 8) {
1670 tcg_gen_not_tl(t0, t0);
1671 }
1672 if (dc->op2 & 4) {
1673 t_gen_swapw(t0, t0);
1674 }
1675 if (dc->op2 & 2) {
1676 t_gen_swapb(t0, t0);
1677 }
1678 if (dc->op2 & 1) {
1679 t_gen_swapr(t0, t0);
1680 }
1681 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op1], cpu_R[dc->op1], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001682 return 2;
ths81700282007-10-08 12:49:08 +00001683}
1684
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001685static int dec_or_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001686{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001687 TCGv t[2];
1688 int size = memsize_zz(dc);
1689 LOG_DIS("or.%c $r%u, $r%u\n",
1690 memsize_char(size), dc->op1, dc->op2);
1691 cris_cc_mask(dc, CC_MASK_NZ);
1692 cris_alu_alloc_temps(dc, size, t);
1693 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1694 cris_alu(dc, CC_OP_OR, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001695 return 2;
ths81700282007-10-08 12:49:08 +00001696}
1697
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001698static int dec_addi_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001699{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001700 TCGv t0;
1701 LOG_DIS("addi.%c $r%u, $r%u\n",
1702 memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
1703 cris_cc_mask(dc, 0);
1704 t0 = tcg_temp_new();
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001705 tcg_gen_shli_tl(t0, cpu_R[dc->op2], dc->zzsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001706 tcg_gen_add_tl(cpu_R[dc->op1], cpu_R[dc->op1], t0);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001707 return 2;
ths81700282007-10-08 12:49:08 +00001708}
1709
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001710static int dec_addi_acr(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001711{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001712 TCGv t0;
1713 LOG_DIS("addi.%c $r%u, $r%u, $acr\n",
1714 memsize_char(memsize_zz(dc)), dc->op2, dc->op1);
1715 cris_cc_mask(dc, 0);
1716 t0 = tcg_temp_new();
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001717 tcg_gen_shli_tl(t0, cpu_R[dc->op2], dc->zzsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001718 tcg_gen_add_tl(cpu_R[R_ACR], cpu_R[dc->op1], t0);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001719 return 2;
ths81700282007-10-08 12:49:08 +00001720}
1721
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001722static int dec_neg_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001723{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001724 TCGv t[2];
1725 int size = memsize_zz(dc);
1726 LOG_DIS("neg.%c $r%u, $r%u\n",
1727 memsize_char(size), dc->op1, dc->op2);
1728 cris_cc_mask(dc, CC_MASK_NZVC);
1729 cris_alu_alloc_temps(dc, size, t);
1730 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
edgar_igl30abcfc2008-05-27 21:10:56 +00001731
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001732 cris_alu(dc, CC_OP_NEG, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001733 return 2;
ths81700282007-10-08 12:49:08 +00001734}
1735
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001736static int dec_btst_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001737{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001738 LOG_DIS("btst $r%u, $r%u\n",
1739 dc->op1, dc->op2);
1740 cris_cc_mask(dc, CC_MASK_NZ);
1741 cris_evaluate_flags(dc);
Richard Hendersonad75a512023-09-13 16:37:36 -07001742 gen_helper_btst(cpu_PR[PR_CCS], tcg_env, cpu_R[dc->op2],
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001743 cpu_R[dc->op1], cpu_PR[PR_CCS]);
1744 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2],
1745 cpu_R[dc->op2], cpu_R[dc->op2], 4);
1746 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
1747 dc->flags_uptodate = 1;
1748 return 2;
ths81700282007-10-08 12:49:08 +00001749}
1750
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001751static int dec_sub_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001752{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001753 TCGv t[2];
1754 int size = memsize_zz(dc);
1755 LOG_DIS("sub.%c $r%u, $r%u\n",
1756 memsize_char(size), dc->op1, dc->op2);
1757 cris_cc_mask(dc, CC_MASK_NZVC);
1758 cris_alu_alloc_temps(dc, size, t);
1759 dec_prep_alu_r(dc, dc->op1, dc->op2, size, 0, t[0], t[1]);
1760 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], size);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001761 return 2;
ths81700282007-10-08 12:49:08 +00001762}
1763
1764/* Zero extension. From size to dword. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001765static int dec_movu_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001766{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001767 TCGv t0;
1768 int size = memsize_z(dc);
1769 LOG_DIS("movu.%c $r%u, $r%u\n",
1770 memsize_char(size),
1771 dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001772
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001773 cris_cc_mask(dc, CC_MASK_NZ);
1774 t0 = tcg_temp_new();
1775 dec_prep_move_r(dc, dc->op1, dc->op2, size, 0, t0);
1776 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001777 return 2;
ths81700282007-10-08 12:49:08 +00001778}
1779
1780/* Sign extension. From size to dword. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001781static int dec_movs_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001782{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001783 TCGv t0;
1784 int size = memsize_z(dc);
1785 LOG_DIS("movs.%c $r%u, $r%u\n",
1786 memsize_char(size),
1787 dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001788
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001789 cris_cc_mask(dc, CC_MASK_NZ);
1790 t0 = tcg_temp_new();
1791 /* Size can only be qi or hi. */
1792 t_gen_sext(t0, cpu_R[dc->op1], size);
1793 cris_alu(dc, CC_OP_MOVE,
1794 cpu_R[dc->op2], cpu_R[dc->op1], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001795 return 2;
ths81700282007-10-08 12:49:08 +00001796}
1797
1798/* zero extension. From size to dword. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001799static int dec_addu_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001800{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001801 TCGv t0;
1802 int size = memsize_z(dc);
1803 LOG_DIS("addu.%c $r%u, $r%u\n",
1804 memsize_char(size),
1805 dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001806
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001807 cris_cc_mask(dc, CC_MASK_NZVC);
1808 t0 = tcg_temp_new();
1809 /* Size can only be qi or hi. */
1810 t_gen_zext(t0, cpu_R[dc->op1], size);
1811 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001812 return 2;
ths81700282007-10-08 12:49:08 +00001813}
edgar_igl05ba7d52008-03-14 01:11:25 +00001814
ths81700282007-10-08 12:49:08 +00001815/* Sign extension. From size to dword. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001816static int dec_adds_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001817{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001818 TCGv t0;
1819 int size = memsize_z(dc);
1820 LOG_DIS("adds.%c $r%u, $r%u\n",
1821 memsize_char(size),
1822 dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001823
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001824 cris_cc_mask(dc, CC_MASK_NZVC);
1825 t0 = tcg_temp_new();
1826 /* Size can only be qi or hi. */
1827 t_gen_sext(t0, cpu_R[dc->op1], size);
1828 cris_alu(dc, CC_OP_ADD,
1829 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001830 return 2;
ths81700282007-10-08 12:49:08 +00001831}
1832
1833/* Zero extension. From size to dword. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001834static int dec_subu_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001835{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001836 TCGv t0;
1837 int size = memsize_z(dc);
1838 LOG_DIS("subu.%c $r%u, $r%u\n",
1839 memsize_char(size),
1840 dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001841
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001842 cris_cc_mask(dc, CC_MASK_NZVC);
1843 t0 = tcg_temp_new();
1844 /* Size can only be qi or hi. */
1845 t_gen_zext(t0, cpu_R[dc->op1], size);
1846 cris_alu(dc, CC_OP_SUB,
1847 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001848 return 2;
ths81700282007-10-08 12:49:08 +00001849}
1850
1851/* Sign extension. From size to dword. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001852static int dec_subs_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001853{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001854 TCGv t0;
1855 int size = memsize_z(dc);
1856 LOG_DIS("subs.%c $r%u, $r%u\n",
1857 memsize_char(size),
1858 dc->op1, dc->op2);
ths81700282007-10-08 12:49:08 +00001859
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001860 cris_cc_mask(dc, CC_MASK_NZVC);
1861 t0 = tcg_temp_new();
1862 /* Size can only be qi or hi. */
1863 t_gen_sext(t0, cpu_R[dc->op1], size);
1864 cris_alu(dc, CC_OP_SUB,
1865 cpu_R[dc->op2], cpu_R[dc->op2], t0, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001866 return 2;
ths81700282007-10-08 12:49:08 +00001867}
1868
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001869static int dec_setclrf(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001870{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001871 uint32_t flags;
1872 int set = (~dc->opcode >> 2) & 1;
ths81700282007-10-08 12:49:08 +00001873
edgar_iglfb48f712008-10-27 16:46:29 +00001874
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001875 flags = (EXTRACT_FIELD(dc->ir, 12, 15) << 4)
1876 | EXTRACT_FIELD(dc->ir, 0, 3);
1877 if (set && flags == 0) {
1878 LOG_DIS("nop\n");
1879 return 2;
1880 } else if (!set && (flags & 0x20)) {
1881 LOG_DIS("di\n");
1882 } else {
1883 LOG_DIS("%sf %x\n", set ? "set" : "clr", flags);
1884 }
ths81700282007-10-08 12:49:08 +00001885
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001886 /* User space is not allowed to touch these. Silently ignore. */
1887 if (dc->tb_flags & U_FLAG) {
1888 flags &= ~(S_FLAG | I_FLAG | U_FLAG);
1889 }
ths81700282007-10-08 12:49:08 +00001890
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001891 if (flags & X_FLAG) {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001892 if (set) {
1893 dc->flags_x = X_FLAG;
1894 } else {
1895 dc->flags_x = 0;
1896 }
1897 }
edgar_igl2a44f7f2008-06-06 11:23:28 +00001898
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001899 /* Break the TB if any of the SPI flag changes. */
1900 if (flags & (P_FLAG | S_FLAG)) {
1901 tcg_gen_movi_tl(env_pc, dc->pc + 2);
Richard Henderson67f69c42021-06-19 19:17:40 -07001902 dc->base.is_jmp = DISAS_UPDATE;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001903 dc->cpustate_changed = 1;
1904 }
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +01001905
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001906 /* For the I flag, only act on posedge. */
1907 if ((flags & I_FLAG)) {
1908 tcg_gen_movi_tl(env_pc, dc->pc + 2);
Richard Henderson67f69c42021-06-19 19:17:40 -07001909 dc->base.is_jmp = DISAS_UPDATE;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001910 dc->cpustate_changed = 1;
1911 }
edgar_igl2a44f7f2008-06-06 11:23:28 +00001912
1913
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001914 /* Simply decode the flags. */
1915 cris_evaluate_flags(dc);
1916 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
1917 cris_update_cc_x(dc);
1918 tcg_gen_movi_tl(cc_op, dc->cc_op);
edgar_iglb41f7df2008-05-02 22:16:17 +00001919
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001920 if (set) {
1921 if (!(dc->tb_flags & U_FLAG) && (flags & U_FLAG)) {
1922 /* Enter user mode. */
1923 t_gen_mov_env_TN(ksp, cpu_R[R_SP]);
1924 tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]);
1925 dc->cpustate_changed = 1;
1926 }
1927 tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags);
1928 } else {
1929 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags);
1930 }
edgar_igldceaf392008-05-07 15:24:53 +00001931
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001932 dc->flags_uptodate = 1;
1933 dc->clear_x = 0;
1934 return 2;
ths81700282007-10-08 12:49:08 +00001935}
1936
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001937static int dec_move_rs(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001938{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001939 TCGv c2, c1;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001940 LOG_DIS("move $r%u, $s%u\n", dc->op1, dc->op2);
Richard Hendersonab554f12023-02-25 12:44:04 -10001941 c1 = tcg_constant_tl(dc->op1);
1942 c2 = tcg_constant_tl(dc->op2);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001943 cris_cc_mask(dc, 0);
Richard Hendersonad75a512023-09-13 16:37:36 -07001944 gen_helper_movl_sreg_reg(tcg_env, c2, c1);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001945 return 2;
ths81700282007-10-08 12:49:08 +00001946}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001947static int dec_move_sr(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001948{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01001949 TCGv c2, c1;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001950 LOG_DIS("move $s%u, $r%u\n", dc->op2, dc->op1);
Richard Hendersonab554f12023-02-25 12:44:04 -10001951 c1 = tcg_constant_tl(dc->op1);
1952 c2 = tcg_constant_tl(dc->op2);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001953 cris_cc_mask(dc, 0);
Richard Hendersonad75a512023-09-13 16:37:36 -07001954 gen_helper_movl_reg_sreg(tcg_env, c1, c2);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001955 return 2;
ths81700282007-10-08 12:49:08 +00001956}
edgar_igldceaf392008-05-07 15:24:53 +00001957
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001958static int dec_move_rp(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001959{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001960 TCGv t[2];
1961 LOG_DIS("move $r%u, $p%u\n", dc->op1, dc->op2);
1962 cris_cc_mask(dc, 0);
edgar_iglb41f7df2008-05-02 22:16:17 +00001963
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001964 t[0] = tcg_temp_new();
1965 if (dc->op2 == PR_CCS) {
1966 cris_evaluate_flags(dc);
Peter Maydell08397c42014-06-07 18:03:01 +01001967 tcg_gen_mov_tl(t[0], cpu_R[dc->op1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001968 if (dc->tb_flags & U_FLAG) {
1969 t[1] = tcg_temp_new();
1970 /* User space is not allowed to touch all flags. */
1971 tcg_gen_andi_tl(t[0], t[0], 0x39f);
1972 tcg_gen_andi_tl(t[1], cpu_PR[PR_CCS], ~0x39f);
1973 tcg_gen_or_tl(t[0], t[1], t[0]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001974 }
1975 } else {
Peter Maydell08397c42014-06-07 18:03:01 +01001976 tcg_gen_mov_tl(t[0], cpu_R[dc->op1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001977 }
edgar_iglb41f7df2008-05-02 22:16:17 +00001978
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001979 t_gen_mov_preg_TN(dc, dc->op2, t[0]);
1980 if (dc->op2 == PR_CCS) {
1981 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
1982 dc->flags_uptodate = 1;
1983 }
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001984 return 2;
ths81700282007-10-08 12:49:08 +00001985}
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02001986static int dec_move_pr(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00001987{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001988 TCGv t0;
1989 LOG_DIS("move $p%u, $r%u\n", dc->op2, dc->op1);
1990 cris_cc_mask(dc, 0);
edgar_igl2a44f7f2008-06-06 11:23:28 +00001991
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001992 if (dc->op2 == PR_CCS) {
1993 cris_evaluate_flags(dc);
1994 }
edgar_igl2a44f7f2008-06-06 11:23:28 +00001995
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04001996 if (dc->op2 == PR_DZ) {
1997 tcg_gen_movi_tl(cpu_R[dc->op1], 0);
1998 } else {
1999 t0 = tcg_temp_new();
2000 t_gen_mov_TN_preg(t0, dc->op2);
2001 cris_alu(dc, CC_OP_MOVE,
2002 cpu_R[dc->op1], cpu_R[dc->op1], t0,
2003 preg_sizes[dc->op2]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002004 }
2005 return 2;
ths81700282007-10-08 12:49:08 +00002006}
2007
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002008static int dec_move_mr(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002009{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002010 int memsize = memsize_zz(dc);
2011 int insn_len;
2012 LOG_DIS("move.%c [$r%u%s, $r%u\n",
2013 memsize_char(memsize),
2014 dc->op1, dc->postinc ? "+]" : "]",
2015 dc->op2);
ths81700282007-10-08 12:49:08 +00002016
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002017 if (memsize == 4) {
2018 insn_len = dec_prep_move_m(env, dc, 0, 4, cpu_R[dc->op2]);
2019 cris_cc_mask(dc, CC_MASK_NZ);
2020 cris_update_cc_op(dc, CC_OP_MOVE, 4);
2021 cris_update_cc_x(dc);
2022 cris_update_result(dc, cpu_R[dc->op2]);
2023 } else {
2024 TCGv t0;
edgar_iglfb48f712008-10-27 16:46:29 +00002025
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002026 t0 = tcg_temp_new();
2027 insn_len = dec_prep_move_m(env, dc, 0, memsize, t0);
2028 cris_cc_mask(dc, CC_MASK_NZ);
2029 cris_alu(dc, CC_OP_MOVE,
2030 cpu_R[dc->op2], cpu_R[dc->op2], t0, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002031 }
2032 do_postinc(dc, memsize);
2033 return insn_len;
ths81700282007-10-08 12:49:08 +00002034}
2035
edgar_igl31c18d82008-10-27 20:24:59 +00002036static inline void cris_alu_m_alloc_temps(TCGv *t)
2037{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002038 t[0] = tcg_temp_new();
2039 t[1] = tcg_temp_new();
edgar_igl31c18d82008-10-27 20:24:59 +00002040}
2041
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002042static int dec_movs_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002043{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002044 TCGv t[2];
2045 int memsize = memsize_z(dc);
2046 int insn_len;
2047 LOG_DIS("movs.%c [$r%u%s, $r%u\n",
2048 memsize_char(memsize),
2049 dc->op1, dc->postinc ? "+]" : "]",
2050 dc->op2);
ths81700282007-10-08 12:49:08 +00002051
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002052 cris_alu_m_alloc_temps(t);
2053 /* sign extend. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002054 insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002055 cris_cc_mask(dc, CC_MASK_NZ);
2056 cris_alu(dc, CC_OP_MOVE,
2057 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2058 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002059 return insn_len;
ths81700282007-10-08 12:49:08 +00002060}
2061
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002062static int dec_addu_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002063{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002064 TCGv t[2];
2065 int memsize = memsize_z(dc);
2066 int insn_len;
2067 LOG_DIS("addu.%c [$r%u%s, $r%u\n",
2068 memsize_char(memsize),
2069 dc->op1, dc->postinc ? "+]" : "]",
2070 dc->op2);
ths81700282007-10-08 12:49:08 +00002071
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002072 cris_alu_m_alloc_temps(t);
2073 /* sign extend. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002074 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002075 cris_cc_mask(dc, CC_MASK_NZVC);
2076 cris_alu(dc, CC_OP_ADD,
2077 cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2078 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002079 return insn_len;
ths81700282007-10-08 12:49:08 +00002080}
2081
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002082static int dec_adds_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002083{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002084 TCGv t[2];
2085 int memsize = memsize_z(dc);
2086 int insn_len;
2087 LOG_DIS("adds.%c [$r%u%s, $r%u\n",
2088 memsize_char(memsize),
2089 dc->op1, dc->postinc ? "+]" : "]",
2090 dc->op2);
ths81700282007-10-08 12:49:08 +00002091
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002092 cris_alu_m_alloc_temps(t);
2093 /* sign extend. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002094 insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002095 cris_cc_mask(dc, CC_MASK_NZVC);
2096 cris_alu(dc, CC_OP_ADD, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2097 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002098 return insn_len;
ths81700282007-10-08 12:49:08 +00002099}
2100
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002101static int dec_subu_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002102{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002103 TCGv t[2];
2104 int memsize = memsize_z(dc);
2105 int insn_len;
2106 LOG_DIS("subu.%c [$r%u%s, $r%u\n",
2107 memsize_char(memsize),
2108 dc->op1, dc->postinc ? "+]" : "]",
2109 dc->op2);
ths81700282007-10-08 12:49:08 +00002110
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002111 cris_alu_m_alloc_temps(t);
2112 /* sign extend. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002113 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002114 cris_cc_mask(dc, CC_MASK_NZVC);
2115 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2116 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002117 return insn_len;
ths81700282007-10-08 12:49:08 +00002118}
2119
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002120static int dec_subs_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002121{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002122 TCGv t[2];
2123 int memsize = memsize_z(dc);
2124 int insn_len;
2125 LOG_DIS("subs.%c [$r%u%s, $r%u\n",
2126 memsize_char(memsize),
2127 dc->op1, dc->postinc ? "+]" : "]",
2128 dc->op2);
ths81700282007-10-08 12:49:08 +00002129
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002130 cris_alu_m_alloc_temps(t);
2131 /* sign extend. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002132 insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002133 cris_cc_mask(dc, CC_MASK_NZVC);
2134 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2135 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002136 return insn_len;
ths81700282007-10-08 12:49:08 +00002137}
2138
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002139static int dec_movu_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002140{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002141 TCGv t[2];
2142 int memsize = memsize_z(dc);
2143 int insn_len;
ths81700282007-10-08 12:49:08 +00002144
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002145 LOG_DIS("movu.%c [$r%u%s, $r%u\n",
2146 memsize_char(memsize),
2147 dc->op1, dc->postinc ? "+]" : "]",
2148 dc->op2);
ths81700282007-10-08 12:49:08 +00002149
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002150 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002151 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002152 cris_cc_mask(dc, CC_MASK_NZ);
2153 cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2154 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002155 return insn_len;
ths81700282007-10-08 12:49:08 +00002156}
2157
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002158static int dec_cmpu_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002159{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002160 TCGv t[2];
2161 int memsize = memsize_z(dc);
2162 int insn_len;
2163 LOG_DIS("cmpu.%c [$r%u%s, $r%u\n",
2164 memsize_char(memsize),
2165 dc->op1, dc->postinc ? "+]" : "]",
2166 dc->op2);
ths81700282007-10-08 12:49:08 +00002167
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002168 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002169 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002170 cris_cc_mask(dc, CC_MASK_NZVC);
2171 cris_alu(dc, CC_OP_CMP, cpu_R[dc->op2], cpu_R[dc->op2], t[1], 4);
2172 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002173 return insn_len;
ths81700282007-10-08 12:49:08 +00002174}
2175
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002176static int dec_cmps_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002177{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002178 TCGv t[2];
2179 int memsize = memsize_z(dc);
2180 int insn_len;
2181 LOG_DIS("cmps.%c [$r%u%s, $r%u\n",
2182 memsize_char(memsize),
2183 dc->op1, dc->postinc ? "+]" : "]",
2184 dc->op2);
ths81700282007-10-08 12:49:08 +00002185
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002186 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002187 insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002188 cris_cc_mask(dc, CC_MASK_NZVC);
2189 cris_alu(dc, CC_OP_CMP,
2190 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
2191 memsize_zz(dc));
2192 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002193 return insn_len;
ths81700282007-10-08 12:49:08 +00002194}
2195
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002196static int dec_cmp_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002197{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002198 TCGv t[2];
2199 int memsize = memsize_zz(dc);
2200 int insn_len;
2201 LOG_DIS("cmp.%c [$r%u%s, $r%u\n",
2202 memsize_char(memsize),
2203 dc->op1, dc->postinc ? "+]" : "]",
2204 dc->op2);
ths81700282007-10-08 12:49:08 +00002205
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002206 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002207 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002208 cris_cc_mask(dc, CC_MASK_NZVC);
2209 cris_alu(dc, CC_OP_CMP,
2210 cpu_R[dc->op2], cpu_R[dc->op2], t[1],
2211 memsize_zz(dc));
2212 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002213 return insn_len;
ths81700282007-10-08 12:49:08 +00002214}
2215
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002216static int dec_test_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002217{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002218 TCGv t[2], c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002219 int memsize = memsize_zz(dc);
2220 int insn_len;
2221 LOG_DIS("test.%c [$r%u%s] op2=%x\n",
2222 memsize_char(memsize),
2223 dc->op1, dc->postinc ? "+]" : "]",
2224 dc->op2);
ths81700282007-10-08 12:49:08 +00002225
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002226 cris_evaluate_flags(dc);
edgar_igldceaf392008-05-07 15:24:53 +00002227
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002228 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002229 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002230 cris_cc_mask(dc, CC_MASK_NZ);
2231 tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3);
edgar_iglb41f7df2008-05-02 22:16:17 +00002232
Richard Hendersonab554f12023-02-25 12:44:04 -10002233 c = tcg_constant_tl(0);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002234 cris_alu(dc, CC_OP_CMP,
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002235 cpu_R[dc->op2], t[1], c, memsize_zz(dc));
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002236 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002237 return insn_len;
ths81700282007-10-08 12:49:08 +00002238}
2239
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002240static int dec_and_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002241{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002242 TCGv t[2];
2243 int memsize = memsize_zz(dc);
2244 int insn_len;
2245 LOG_DIS("and.%c [$r%u%s, $r%u\n",
2246 memsize_char(memsize),
2247 dc->op1, dc->postinc ? "+]" : "]",
2248 dc->op2);
ths81700282007-10-08 12:49:08 +00002249
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002250 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002251 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002252 cris_cc_mask(dc, CC_MASK_NZ);
2253 cris_alu(dc, CC_OP_AND, cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
2254 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002255 return insn_len;
ths81700282007-10-08 12:49:08 +00002256}
2257
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002258static int dec_add_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002259{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002260 TCGv t[2];
2261 int memsize = memsize_zz(dc);
2262 int insn_len;
2263 LOG_DIS("add.%c [$r%u%s, $r%u\n",
2264 memsize_char(memsize),
2265 dc->op1, dc->postinc ? "+]" : "]",
2266 dc->op2);
ths81700282007-10-08 12:49:08 +00002267
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002268 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002269 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002270 cris_cc_mask(dc, CC_MASK_NZVC);
2271 cris_alu(dc, CC_OP_ADD,
2272 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
2273 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002274 return insn_len;
ths81700282007-10-08 12:49:08 +00002275}
2276
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002277static int dec_addo_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002278{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002279 TCGv t[2];
2280 int memsize = memsize_zz(dc);
2281 int insn_len;
2282 LOG_DIS("add.%c [$r%u%s, $r%u\n",
2283 memsize_char(memsize),
2284 dc->op1, dc->postinc ? "+]" : "]",
2285 dc->op2);
ths81700282007-10-08 12:49:08 +00002286
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002287 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002288 insn_len = dec_prep_alu_m(env, dc, 1, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002289 cris_cc_mask(dc, 0);
2290 cris_alu(dc, CC_OP_ADD, cpu_R[R_ACR], t[0], t[1], 4);
2291 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002292 return insn_len;
ths81700282007-10-08 12:49:08 +00002293}
2294
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002295static int dec_bound_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002296{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002297 TCGv l[2];
2298 int memsize = memsize_zz(dc);
2299 int insn_len;
2300 LOG_DIS("bound.%c [$r%u%s, $r%u\n",
2301 memsize_char(memsize),
2302 dc->op1, dc->postinc ? "+]" : "]",
2303 dc->op2);
ths81700282007-10-08 12:49:08 +00002304
Richard Henderson5f153b12023-01-29 14:40:21 -10002305 l[0] = tcg_temp_new();
2306 l[1] = tcg_temp_new();
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002307 insn_len = dec_prep_alu_m(env, dc, 0, memsize, l[0], l[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002308 cris_cc_mask(dc, CC_MASK_NZ);
2309 cris_alu(dc, CC_OP_BOUND, cpu_R[dc->op2], l[0], l[1], 4);
2310 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002311 return insn_len;
ths81700282007-10-08 12:49:08 +00002312}
2313
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002314static int dec_addc_mr(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002315{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002316 TCGv t[2];
2317 int insn_len = 2;
2318 LOG_DIS("addc [$r%u%s, $r%u\n",
2319 dc->op1, dc->postinc ? "+]" : "]",
2320 dc->op2);
ths81700282007-10-08 12:49:08 +00002321
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002322 cris_evaluate_flags(dc);
edgar_igla8cf66b2009-01-07 12:25:15 +00002323
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002324 /* Set for this insn. */
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002325 dc->flags_x = X_FLAG;
edgar_igla8cf66b2009-01-07 12:25:15 +00002326
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002327 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002328 insn_len = dec_prep_alu_m(env, dc, 0, 4, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002329 cris_cc_mask(dc, CC_MASK_NZVC);
2330 cris_alu(dc, CC_OP_ADDC, cpu_R[dc->op2], t[0], t[1], 4);
2331 do_postinc(dc, 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002332 return insn_len;
ths81700282007-10-08 12:49:08 +00002333}
2334
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002335static int dec_sub_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002336{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002337 TCGv t[2];
2338 int memsize = memsize_zz(dc);
2339 int insn_len;
2340 LOG_DIS("sub.%c [$r%u%s, $r%u ir=%x zz=%x\n",
2341 memsize_char(memsize),
2342 dc->op1, dc->postinc ? "+]" : "]",
2343 dc->op2, dc->ir, dc->zzsize);
ths81700282007-10-08 12:49:08 +00002344
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002345 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002346 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002347 cris_cc_mask(dc, CC_MASK_NZVC);
2348 cris_alu(dc, CC_OP_SUB, cpu_R[dc->op2], t[0], t[1], memsize);
2349 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002350 return insn_len;
ths81700282007-10-08 12:49:08 +00002351}
2352
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002353static int dec_or_m(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002354{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002355 TCGv t[2];
2356 int memsize = memsize_zz(dc);
2357 int insn_len;
2358 LOG_DIS("or.%c [$r%u%s, $r%u pc=%x\n",
2359 memsize_char(memsize),
2360 dc->op1, dc->postinc ? "+]" : "]",
2361 dc->op2, dc->pc);
ths81700282007-10-08 12:49:08 +00002362
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002363 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002364 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002365 cris_cc_mask(dc, CC_MASK_NZ);
2366 cris_alu(dc, CC_OP_OR,
2367 cpu_R[dc->op2], t[0], t[1], memsize_zz(dc));
2368 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002369 return insn_len;
ths81700282007-10-08 12:49:08 +00002370}
2371
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002372static int dec_move_mp(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002373{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002374 TCGv t[2];
2375 int memsize = memsize_zz(dc);
2376 int insn_len = 2;
ths81700282007-10-08 12:49:08 +00002377
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002378 LOG_DIS("move.%c [$r%u%s, $p%u\n",
2379 memsize_char(memsize),
2380 dc->op1,
2381 dc->postinc ? "+]" : "]",
2382 dc->op2);
ths81700282007-10-08 12:49:08 +00002383
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002384 cris_alu_m_alloc_temps(t);
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002385 insn_len = dec_prep_alu_m(env, dc, 0, memsize, t[0], t[1]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002386 cris_cc_mask(dc, 0);
2387 if (dc->op2 == PR_CCS) {
2388 cris_evaluate_flags(dc);
2389 if (dc->tb_flags & U_FLAG) {
2390 /* User space is not allowed to touch all flags. */
2391 tcg_gen_andi_tl(t[1], t[1], 0x39f);
2392 tcg_gen_andi_tl(t[0], cpu_PR[PR_CCS], ~0x39f);
2393 tcg_gen_or_tl(t[1], t[0], t[1]);
2394 }
2395 }
edgar_iglb41f7df2008-05-02 22:16:17 +00002396
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002397 t_gen_mov_preg_TN(dc, dc->op2, t[1]);
ths81700282007-10-08 12:49:08 +00002398
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002399 do_postinc(dc, memsize);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002400 return insn_len;
ths81700282007-10-08 12:49:08 +00002401}
2402
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002403static int dec_move_pm(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002404{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002405 TCGv t0;
2406 int memsize;
ths81700282007-10-08 12:49:08 +00002407
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002408 memsize = preg_sizes[dc->op2];
ths81700282007-10-08 12:49:08 +00002409
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002410 LOG_DIS("move.%c $p%u, [$r%u%s\n",
2411 memsize_char(memsize),
2412 dc->op2, dc->op1, dc->postinc ? "+]" : "]");
ths81700282007-10-08 12:49:08 +00002413
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002414 /* prepare store. Address in T0, value in T1. */
2415 if (dc->op2 == PR_CCS) {
2416 cris_evaluate_flags(dc);
2417 }
2418 t0 = tcg_temp_new();
2419 t_gen_mov_TN_preg(t0, dc->op2);
2420 cris_flush_cc_state(dc);
2421 gen_store(dc, cpu_R[dc->op1], t0, memsize);
edgar_igl17ac9752008-05-06 08:30:15 +00002422
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002423 cris_cc_mask(dc, 0);
2424 if (dc->postinc) {
2425 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
2426 }
2427 return 2;
ths81700282007-10-08 12:49:08 +00002428}
2429
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002430static int dec_movem_mr(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002431{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002432 TCGv_i64 tmp[16];
2433 TCGv tmp32;
2434 TCGv addr;
2435 int i;
2436 int nr = dc->op2 + 1;
ths81700282007-10-08 12:49:08 +00002437
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002438 LOG_DIS("movem [$r%u%s, $r%u\n", dc->op1,
2439 dc->postinc ? "+]" : "]", dc->op2);
ths81700282007-10-08 12:49:08 +00002440
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002441 addr = tcg_temp_new();
2442 /* There are probably better ways of doing this. */
2443 cris_flush_cc_state(dc);
2444 for (i = 0; i < (nr >> 1); i++) {
2445 tmp[i] = tcg_temp_new_i64();
2446 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
2447 gen_load64(dc, tmp[i], addr);
2448 }
2449 if (nr & 1) {
2450 tmp32 = tcg_temp_new_i32();
2451 tcg_gen_addi_tl(addr, cpu_R[dc->op1], i * 8);
2452 gen_load(dc, tmp32, addr, 4, 0);
2453 } else {
Richard Hendersonf7647182017-11-02 12:47:37 +01002454 tmp32 = NULL;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002455 }
edgar_igl17ac9752008-05-06 08:30:15 +00002456
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002457 for (i = 0; i < (nr >> 1); i++) {
Richard Hendersonecc7b3a2015-07-24 11:49:53 -07002458 tcg_gen_extrl_i64_i32(cpu_R[i * 2], tmp[i]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002459 tcg_gen_shri_i64(tmp[i], tmp[i], 32);
Richard Hendersonecc7b3a2015-07-24 11:49:53 -07002460 tcg_gen_extrl_i64_i32(cpu_R[i * 2 + 1], tmp[i]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002461 }
2462 if (nr & 1) {
2463 tcg_gen_mov_tl(cpu_R[dc->op2], tmp32);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002464 }
edgar_igl17ac9752008-05-06 08:30:15 +00002465
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002466 /* writeback the updated pointer value. */
2467 if (dc->postinc) {
2468 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4);
2469 }
edgar_iglb41f7df2008-05-02 22:16:17 +00002470
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002471 /* gen_load might want to evaluate the previous insns flags. */
2472 cris_cc_mask(dc, 0);
2473 return 2;
ths81700282007-10-08 12:49:08 +00002474}
2475
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002476static int dec_movem_rm(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002477{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002478 TCGv tmp;
2479 TCGv addr;
2480 int i;
ths81700282007-10-08 12:49:08 +00002481
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002482 LOG_DIS("movem $r%u, [$r%u%s\n", dc->op2, dc->op1,
2483 dc->postinc ? "+]" : "]");
ths81700282007-10-08 12:49:08 +00002484
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002485 cris_flush_cc_state(dc);
edgar_igl30abcfc2008-05-27 21:10:56 +00002486
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002487 tmp = tcg_temp_new();
2488 addr = tcg_temp_new();
2489 tcg_gen_movi_tl(tmp, 4);
2490 tcg_gen_mov_tl(addr, cpu_R[dc->op1]);
2491 for (i = 0; i <= dc->op2; i++) {
2492 /* Displace addr. */
2493 /* Perform the store. */
2494 gen_store(dc, addr, cpu_R[i], 4);
2495 tcg_gen_add_tl(addr, addr, tmp);
2496 }
2497 if (dc->postinc) {
2498 tcg_gen_mov_tl(cpu_R[dc->op1], addr);
2499 }
2500 cris_cc_mask(dc, 0);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002501 return 2;
ths81700282007-10-08 12:49:08 +00002502}
2503
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002504static int dec_move_rm(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002505{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002506 int memsize;
ths81700282007-10-08 12:49:08 +00002507
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002508 memsize = memsize_zz(dc);
ths81700282007-10-08 12:49:08 +00002509
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002510 LOG_DIS("move.%c $r%u, [$r%u]\n",
2511 memsize_char(memsize), dc->op2, dc->op1);
ths81700282007-10-08 12:49:08 +00002512
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002513 /* prepare store. */
2514 cris_flush_cc_state(dc);
2515 gen_store(dc, cpu_R[dc->op1], cpu_R[dc->op2], memsize);
edgar_igl17ac9752008-05-06 08:30:15 +00002516
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002517 if (dc->postinc) {
2518 tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], memsize);
2519 }
2520 cris_cc_mask(dc, 0);
2521 return 2;
ths81700282007-10-08 12:49:08 +00002522}
2523
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002524static int dec_lapcq(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002525{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002526 LOG_DIS("lapcq %x, $r%u\n",
2527 dc->pc + dc->op1*2, dc->op2);
2528 cris_cc_mask(dc, 0);
2529 tcg_gen_movi_tl(cpu_R[dc->op2], dc->pc + dc->op1 * 2);
2530 return 2;
ths81700282007-10-08 12:49:08 +00002531}
2532
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002533static int dec_lapc_im(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002534{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002535 unsigned int rd;
2536 int32_t imm;
2537 int32_t pc;
ths81700282007-10-08 12:49:08 +00002538
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002539 rd = dc->op2;
ths81700282007-10-08 12:49:08 +00002540
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002541 cris_cc_mask(dc, 0);
2542 imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
2543 LOG_DIS("lapc 0x%x, $r%u\n", imm + dc->pc, dc->op2);
edgar_iglb41f7df2008-05-02 22:16:17 +00002544
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002545 pc = dc->pc;
2546 pc += imm;
2547 tcg_gen_movi_tl(cpu_R[rd], pc);
2548 return 6;
ths81700282007-10-08 12:49:08 +00002549}
2550
2551/* Jump to special reg. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002552static int dec_jump_p(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002553{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002554 LOG_DIS("jump $p%u\n", dc->op2);
edgar_iglb41f7df2008-05-02 22:16:17 +00002555
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002556 if (dc->op2 == PR_CCS) {
2557 cris_evaluate_flags(dc);
2558 }
2559 t_gen_mov_TN_preg(env_btarget, dc->op2);
2560 /* rete will often have low bit set to indicate delayslot. */
2561 tcg_gen_andi_tl(env_btarget, env_btarget, ~1);
2562 cris_cc_mask(dc, 0);
2563 cris_prepare_jmp(dc, JMP_INDIRECT);
2564 return 2;
ths81700282007-10-08 12:49:08 +00002565}
2566
2567/* Jump and save. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002568static int dec_jas_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002569{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002570 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002571 LOG_DIS("jas $r%u, $p%u\n", dc->op1, dc->op2);
2572 cris_cc_mask(dc, 0);
2573 /* Store the return address in Pd. */
2574 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
2575 if (dc->op2 > 15) {
2576 abort();
2577 }
Richard Hendersonab554f12023-02-25 12:44:04 -10002578 c = tcg_constant_tl(dc->pc + 4);
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002579 t_gen_mov_preg_TN(dc, dc->op2, c);
edgar_iglb41f7df2008-05-02 22:16:17 +00002580
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002581 cris_prepare_jmp(dc, JMP_INDIRECT);
2582 return 2;
ths81700282007-10-08 12:49:08 +00002583}
2584
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002585static int dec_jas_im(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002586{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002587 uint32_t imm;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002588 TCGv c;
ths81700282007-10-08 12:49:08 +00002589
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002590 imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
ths81700282007-10-08 12:49:08 +00002591
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002592 LOG_DIS("jas 0x%x\n", imm);
2593 cris_cc_mask(dc, 0);
Richard Hendersonab554f12023-02-25 12:44:04 -10002594 c = tcg_constant_tl(dc->pc + 8);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002595 /* Store the return address in Pd. */
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002596 t_gen_mov_preg_TN(dc, dc->op2, c);
edgar_igl2a44f7f2008-06-06 11:23:28 +00002597
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002598 dc->jmp_pc = imm;
2599 cris_prepare_jmp(dc, JMP_DIRECT);
2600 return 6;
ths81700282007-10-08 12:49:08 +00002601}
2602
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002603static int dec_jasc_im(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002604{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002605 uint32_t imm;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002606 TCGv c;
ths81700282007-10-08 12:49:08 +00002607
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002608 imm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
ths81700282007-10-08 12:49:08 +00002609
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002610 LOG_DIS("jasc 0x%x\n", imm);
2611 cris_cc_mask(dc, 0);
Richard Hendersonab554f12023-02-25 12:44:04 -10002612 c = tcg_constant_tl(dc->pc + 8 + 4);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002613 /* Store the return address in Pd. */
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002614 t_gen_mov_preg_TN(dc, dc->op2, c);
edgar_igl2a44f7f2008-06-06 11:23:28 +00002615
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002616 dc->jmp_pc = imm;
2617 cris_prepare_jmp(dc, JMP_DIRECT);
2618 return 6;
ths81700282007-10-08 12:49:08 +00002619}
2620
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002621static int dec_jasc_r(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002622{
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002623 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002624 LOG_DIS("jasc_r $r%u, $p%u\n", dc->op1, dc->op2);
2625 cris_cc_mask(dc, 0);
2626 /* Store the return address in Pd. */
2627 tcg_gen_mov_tl(env_btarget, cpu_R[dc->op1]);
Richard Hendersonab554f12023-02-25 12:44:04 -10002628 c = tcg_constant_tl(dc->pc + 4 + 4);
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002629 t_gen_mov_preg_TN(dc, dc->op2, c);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002630 cris_prepare_jmp(dc, JMP_INDIRECT);
2631 return 2;
ths81700282007-10-08 12:49:08 +00002632}
2633
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002634static int dec_bcc_im(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002635{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002636 int32_t offset;
2637 uint32_t cond = dc->op2;
ths81700282007-10-08 12:49:08 +00002638
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002639 offset = cris_fetch(env, dc, dc->pc + 2, 2, 1);
ths81700282007-10-08 12:49:08 +00002640
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002641 LOG_DIS("b%s %d pc=%x dst=%x\n",
2642 cc_name(cond), offset,
2643 dc->pc, dc->pc + offset);
ths81700282007-10-08 12:49:08 +00002644
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002645 cris_cc_mask(dc, 0);
2646 /* op2 holds the condition-code. */
2647 cris_prepare_cc_branch(dc, offset, cond);
2648 return 4;
ths81700282007-10-08 12:49:08 +00002649}
2650
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002651static int dec_bas_im(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002652{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002653 int32_t simm;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002654 TCGv c;
ths81700282007-10-08 12:49:08 +00002655
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002656 simm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
ths81700282007-10-08 12:49:08 +00002657
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002658 LOG_DIS("bas 0x%x, $p%u\n", dc->pc + simm, dc->op2);
2659 cris_cc_mask(dc, 0);
Richard Hendersonab554f12023-02-25 12:44:04 -10002660 c = tcg_constant_tl(dc->pc + 8);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002661 /* Store the return address in Pd. */
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002662 t_gen_mov_preg_TN(dc, dc->op2, c);
ths81700282007-10-08 12:49:08 +00002663
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002664 dc->jmp_pc = dc->pc + simm;
2665 cris_prepare_jmp(dc, JMP_DIRECT);
2666 return 6;
ths81700282007-10-08 12:49:08 +00002667}
2668
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002669static int dec_basc_im(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002670{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002671 int32_t simm;
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002672 TCGv c;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002673 simm = cris_fetch(env, dc, dc->pc + 2, 4, 0);
ths81700282007-10-08 12:49:08 +00002674
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002675 LOG_DIS("basc 0x%x, $p%u\n", dc->pc + simm, dc->op2);
2676 cris_cc_mask(dc, 0);
Richard Hendersonab554f12023-02-25 12:44:04 -10002677 c = tcg_constant_tl(dc->pc + 12);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002678 /* Store the return address in Pd. */
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002679 t_gen_mov_preg_TN(dc, dc->op2, c);
edgar_igl2a44f7f2008-06-06 11:23:28 +00002680
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002681 dc->jmp_pc = dc->pc + simm;
2682 cris_prepare_jmp(dc, JMP_DIRECT);
2683 return 6;
ths81700282007-10-08 12:49:08 +00002684}
2685
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002686static int dec_rfe_etc(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002687{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002688 cris_cc_mask(dc, 0);
ths81700282007-10-08 12:49:08 +00002689
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002690 if (dc->op2 == 15) {
Richard Hendersonad75a512023-09-13 16:37:36 -07002691 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
Andreas Färber259186a2013-01-17 18:51:17 +01002692 -offsetof(CRISCPU, env) + offsetof(CPUState, halted));
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002693 tcg_gen_movi_tl(env_pc, dc->pc + 2);
2694 t_gen_raise_exception(EXCP_HLT);
Richard Henderson1dd09c42021-06-19 20:24:37 -07002695 dc->base.is_jmp = DISAS_NORETURN;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002696 return 2;
2697 }
ths81700282007-10-08 12:49:08 +00002698
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002699 switch (dc->op2 & 7) {
2700 case 2:
2701 /* rfe. */
2702 LOG_DIS("rfe\n");
2703 cris_evaluate_flags(dc);
Richard Hendersonad75a512023-09-13 16:37:36 -07002704 gen_helper_rfe(tcg_env);
Richard Henderson67f69c42021-06-19 19:17:40 -07002705 dc->base.is_jmp = DISAS_UPDATE;
Richard Henderson9e9f5ba2021-06-23 07:08:40 -07002706 dc->cpustate_changed = true;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002707 break;
2708 case 5:
2709 /* rfn. */
2710 LOG_DIS("rfn\n");
2711 cris_evaluate_flags(dc);
Richard Hendersonad75a512023-09-13 16:37:36 -07002712 gen_helper_rfn(tcg_env);
Richard Henderson67f69c42021-06-19 19:17:40 -07002713 dc->base.is_jmp = DISAS_UPDATE;
Richard Henderson9e9f5ba2021-06-23 07:08:40 -07002714 dc->cpustate_changed = true;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002715 break;
2716 case 6:
2717 LOG_DIS("break %d\n", dc->op1);
2718 cris_evaluate_flags(dc);
2719 /* break. */
2720 tcg_gen_movi_tl(env_pc, dc->pc + 2);
edgar_igla1aebcb2008-10-07 22:48:41 +00002721
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002722 /* Breaks start at 16 in the exception vector. */
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002723 t_gen_movi_env_TN(trap_vector, dc->op1 + 16);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002724 t_gen_raise_exception(EXCP_BREAK);
Richard Henderson1dd09c42021-06-19 20:24:37 -07002725 dc->base.is_jmp = DISAS_NORETURN;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002726 break;
2727 default:
2728 printf("op2=%x\n", dc->op2);
2729 BUG();
2730 break;
ths81700282007-10-08 12:49:08 +00002731
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002732 }
2733 return 2;
ths81700282007-10-08 12:49:08 +00002734}
2735
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002736static int dec_ftag_fidx_d_m(CPUCRISState *env, DisasContext *dc)
edgar_igl5d4a5342008-02-25 09:58:22 +00002737{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002738 return 2;
edgar_igl5d4a5342008-02-25 09:58:22 +00002739}
2740
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002741static int dec_ftag_fidx_i_m(CPUCRISState *env, DisasContext *dc)
edgar_igl5d4a5342008-02-25 09:58:22 +00002742{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002743 return 2;
edgar_igl5d4a5342008-02-25 09:58:22 +00002744}
2745
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002746static int dec_null(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002747{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002748 printf("unknown insn pc=%x opc=%x op1=%x op2=%x\n",
2749 dc->pc, dc->opcode, dc->op1, dc->op2);
2750 fflush(NULL);
2751 BUG();
2752 return 2;
ths81700282007-10-08 12:49:08 +00002753}
2754
Richard Henderson5899ce62021-06-19 20:57:31 -07002755static const struct decoder_info {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002756 struct {
2757 uint32_t bits;
2758 uint32_t mask;
2759 };
2760 int (*dec)(CPUCRISState *env, DisasContext *dc);
ths81700282007-10-08 12:49:08 +00002761} decinfo[] = {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002762 /* Order matters here. */
2763 {DEC_MOVEQ, dec_moveq},
2764 {DEC_BTSTQ, dec_btstq},
2765 {DEC_CMPQ, dec_cmpq},
2766 {DEC_ADDOQ, dec_addoq},
2767 {DEC_ADDQ, dec_addq},
2768 {DEC_SUBQ, dec_subq},
2769 {DEC_ANDQ, dec_andq},
2770 {DEC_ORQ, dec_orq},
2771 {DEC_ASRQ, dec_asrq},
2772 {DEC_LSLQ, dec_lslq},
2773 {DEC_LSRQ, dec_lsrq},
2774 {DEC_BCCQ, dec_bccq},
ths81700282007-10-08 12:49:08 +00002775
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002776 {DEC_BCC_IM, dec_bcc_im},
2777 {DEC_JAS_IM, dec_jas_im},
2778 {DEC_JAS_R, dec_jas_r},
2779 {DEC_JASC_IM, dec_jasc_im},
2780 {DEC_JASC_R, dec_jasc_r},
2781 {DEC_BAS_IM, dec_bas_im},
2782 {DEC_BASC_IM, dec_basc_im},
2783 {DEC_JUMP_P, dec_jump_p},
2784 {DEC_LAPC_IM, dec_lapc_im},
2785 {DEC_LAPCQ, dec_lapcq},
ths81700282007-10-08 12:49:08 +00002786
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002787 {DEC_RFE_ETC, dec_rfe_etc},
2788 {DEC_ADDC_MR, dec_addc_mr},
ths81700282007-10-08 12:49:08 +00002789
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002790 {DEC_MOVE_MP, dec_move_mp},
2791 {DEC_MOVE_PM, dec_move_pm},
2792 {DEC_MOVEM_MR, dec_movem_mr},
2793 {DEC_MOVEM_RM, dec_movem_rm},
2794 {DEC_MOVE_PR, dec_move_pr},
2795 {DEC_SCC_R, dec_scc_r},
2796 {DEC_SETF, dec_setclrf},
2797 {DEC_CLEARF, dec_setclrf},
ths81700282007-10-08 12:49:08 +00002798
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002799 {DEC_MOVE_SR, dec_move_sr},
2800 {DEC_MOVE_RP, dec_move_rp},
2801 {DEC_SWAP_R, dec_swap_r},
2802 {DEC_ABS_R, dec_abs_r},
2803 {DEC_LZ_R, dec_lz_r},
2804 {DEC_MOVE_RS, dec_move_rs},
2805 {DEC_BTST_R, dec_btst_r},
2806 {DEC_ADDC_R, dec_addc_r},
ths81700282007-10-08 12:49:08 +00002807
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002808 {DEC_DSTEP_R, dec_dstep_r},
2809 {DEC_XOR_R, dec_xor_r},
2810 {DEC_MCP_R, dec_mcp_r},
2811 {DEC_CMP_R, dec_cmp_r},
ths81700282007-10-08 12:49:08 +00002812
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002813 {DEC_ADDI_R, dec_addi_r},
2814 {DEC_ADDI_ACR, dec_addi_acr},
ths81700282007-10-08 12:49:08 +00002815
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002816 {DEC_ADD_R, dec_add_r},
2817 {DEC_SUB_R, dec_sub_r},
ths81700282007-10-08 12:49:08 +00002818
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002819 {DEC_ADDU_R, dec_addu_r},
2820 {DEC_ADDS_R, dec_adds_r},
2821 {DEC_SUBU_R, dec_subu_r},
2822 {DEC_SUBS_R, dec_subs_r},
2823 {DEC_LSL_R, dec_lsl_r},
ths81700282007-10-08 12:49:08 +00002824
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002825 {DEC_AND_R, dec_and_r},
2826 {DEC_OR_R, dec_or_r},
2827 {DEC_BOUND_R, dec_bound_r},
2828 {DEC_ASR_R, dec_asr_r},
2829 {DEC_LSR_R, dec_lsr_r},
ths81700282007-10-08 12:49:08 +00002830
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002831 {DEC_MOVU_R, dec_movu_r},
2832 {DEC_MOVS_R, dec_movs_r},
2833 {DEC_NEG_R, dec_neg_r},
2834 {DEC_MOVE_R, dec_move_r},
ths81700282007-10-08 12:49:08 +00002835
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002836 {DEC_FTAG_FIDX_I_M, dec_ftag_fidx_i_m},
2837 {DEC_FTAG_FIDX_D_M, dec_ftag_fidx_d_m},
ths81700282007-10-08 12:49:08 +00002838
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002839 {DEC_MULS_R, dec_muls_r},
2840 {DEC_MULU_R, dec_mulu_r},
ths81700282007-10-08 12:49:08 +00002841
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002842 {DEC_ADDU_M, dec_addu_m},
2843 {DEC_ADDS_M, dec_adds_m},
2844 {DEC_SUBU_M, dec_subu_m},
2845 {DEC_SUBS_M, dec_subs_m},
ths81700282007-10-08 12:49:08 +00002846
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002847 {DEC_CMPU_M, dec_cmpu_m},
2848 {DEC_CMPS_M, dec_cmps_m},
2849 {DEC_MOVU_M, dec_movu_m},
2850 {DEC_MOVS_M, dec_movs_m},
ths81700282007-10-08 12:49:08 +00002851
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002852 {DEC_CMP_M, dec_cmp_m},
2853 {DEC_ADDO_M, dec_addo_m},
2854 {DEC_BOUND_M, dec_bound_m},
2855 {DEC_ADD_M, dec_add_m},
2856 {DEC_SUB_M, dec_sub_m},
2857 {DEC_AND_M, dec_and_m},
2858 {DEC_OR_M, dec_or_m},
2859 {DEC_MOVE_RM, dec_move_rm},
2860 {DEC_TEST_M, dec_test_m},
2861 {DEC_MOVE_MR, dec_move_mr},
ths81700282007-10-08 12:49:08 +00002862
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002863 {{0, 0}, dec_null}
ths81700282007-10-08 12:49:08 +00002864};
2865
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002866static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
ths81700282007-10-08 12:49:08 +00002867{
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002868 int insn_len = 2;
2869 int i;
ths81700282007-10-08 12:49:08 +00002870
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002871 /* Load a halfword onto the instruction register. */
Aurelien Jarnocf7e0c82012-09-07 16:13:27 +02002872 dc->ir = cris_fetch(env, dc, dc->pc, 2, 0);
ths81700282007-10-08 12:49:08 +00002873
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002874 /* Now decode it. */
2875 dc->opcode = EXTRACT_FIELD(dc->ir, 4, 11);
2876 dc->op1 = EXTRACT_FIELD(dc->ir, 0, 3);
2877 dc->op2 = EXTRACT_FIELD(dc->ir, 12, 15);
2878 dc->zsize = EXTRACT_FIELD(dc->ir, 4, 4);
2879 dc->zzsize = EXTRACT_FIELD(dc->ir, 4, 5);
2880 dc->postinc = EXTRACT_FIELD(dc->ir, 10, 10);
ths81700282007-10-08 12:49:08 +00002881
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002882 /* Large switch for all insns. */
2883 for (i = 0; i < ARRAY_SIZE(decinfo); i++) {
2884 if ((dc->opcode & decinfo[i].mask) == decinfo[i].bits) {
2885 insn_len = decinfo[i].dec(env, dc);
2886 break;
2887 }
2888 }
ths81700282007-10-08 12:49:08 +00002889
edgar_igldd20fcd2008-10-08 08:28:16 +00002890#if !defined(CONFIG_USER_ONLY)
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002891 /* Single-stepping ? */
2892 if (dc->tb_flags & S_FLAG) {
Richard Henderson42a268c2015-02-13 12:51:55 -08002893 TCGLabel *l1 = gen_new_label();
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002894 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_PR[PR_SPC], dc->pc, l1);
2895 /* We treat SPC as a break with an odd trap vector. */
2896 cris_evaluate_flags(dc);
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01002897 t_gen_movi_env_TN(trap_vector, 3);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002898 tcg_gen_movi_tl(env_pc, dc->pc + insn_len);
2899 tcg_gen_movi_tl(cpu_PR[PR_SPC], dc->pc + insn_len);
2900 t_gen_raise_exception(EXCP_BREAK);
2901 gen_set_label(l1);
2902 }
edgar_igla1aebcb2008-10-07 22:48:41 +00002903#endif
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002904 return insn_len;
ths81700282007-10-08 12:49:08 +00002905}
2906
Paolo Bonzini139c1832020-02-04 12:41:01 +01002907#include "translate_v10.c.inc"
edgar_iglcf1d97f2008-05-13 10:59:14 +00002908
2909/*
2910 * Delay slots on QEMU/CRIS.
2911 *
2912 * If an exception hits on a delayslot, the core will let ERP (the Exception
2913 * Return Pointer) point to the branch (the previous) insn and set the lsb to
2914 * to give SW a hint that the exception actually hit on the dslot.
2915 *
2916 * CRIS expects all PC addresses to be 16-bit aligned. The lsb is ignored by
2917 * the core and any jmp to an odd addresses will mask off that lsb. It is
2918 * simply there to let sw know there was an exception on a dslot.
2919 *
2920 * When the software returns from an exception, the branch will re-execute.
2921 * On QEMU care needs to be taken when a branch+delayslot sequence is broken
Stefan Weilcb8d4c82016-03-23 15:59:57 +01002922 * and the branch and delayslot don't share pages.
edgar_iglcf1d97f2008-05-13 10:59:14 +00002923 *
Michael Tokarev8b819682023-07-14 14:23:51 +03002924 * The TB containing the branch insn will set up env->btarget and evaluate
edgar_iglcf1d97f2008-05-13 10:59:14 +00002925 * env->btaken. When the translation loop exits we will note that the branch
2926 * sequence is broken and let env->dslot be the size of the branch insn (those
2927 * vary in length).
2928 *
Michael Tokarev8b819682023-07-14 14:23:51 +03002929 * The TB containing the delayslot will have the PC of its real insn (i.e no lsb
edgar_iglcf1d97f2008-05-13 10:59:14 +00002930 * set). It will also expect to have env->dslot setup with the size of the
2931 * delay slot so that env->pc - env->dslot point to the branch insn. This TB
2932 * will execute the dslot and take the branch, either to btarget or just one
2933 * insn ahead.
2934 *
2935 * When exceptions occur, we check for env->dslot in do_interrupt to detect
2936 * broken branch sequences and setup $erp accordingly (i.e let it point to the
2937 * branch and set lsb). Then env->dslot gets cleared so that the exception
2938 * handler can enter. When returning from exceptions (jump $erp) the lsb gets
2939 * masked off and we will reexecute the branch insn.
2940 *
2941 */
2942
Richard Henderson330ca142021-06-19 20:49:26 -07002943static void cris_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ths81700282007-10-08 12:49:08 +00002944{
Richard Henderson330ca142021-06-19 20:49:26 -07002945 DisasContext *dc = container_of(dcbase, DisasContext, base);
Richard Hendersonb77af262023-09-13 17:22:49 -07002946 CPUCRISState *env = cpu_env(cs);
Richard Henderson330ca142021-06-19 20:49:26 -07002947 uint32_t tb_flags = dc->base.tb->flags;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002948 uint32_t pc_start;
ths81700282007-10-08 12:49:08 +00002949
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002950 if (env->pregs[PR_VR] == 32) {
2951 dc->decoder = crisv32_decoder;
2952 dc->clear_locked_irq = 0;
2953 } else {
2954 dc->decoder = crisv10_decoder;
2955 dc->clear_locked_irq = 1;
2956 }
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +01002957
Richard Henderson330ca142021-06-19 20:49:26 -07002958 /*
2959 * Odd PC indicates that branch is rexecuting due to exception in the
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002960 * delayslot, like in real hw.
2961 */
Richard Henderson330ca142021-06-19 20:49:26 -07002962 pc_start = dc->base.pc_first & ~1;
Richard Henderson67f69c42021-06-19 19:17:40 -07002963 dc->base.pc_first = pc_start;
2964 dc->base.pc_next = pc_start;
Richard Henderson67f69c42021-06-19 19:17:40 -07002965
2966 dc->cpu = env_archcpu(env);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002967 dc->ppc = pc_start;
2968 dc->pc = pc_start;
Richard Henderson3b916142024-01-29 20:35:06 +10002969 dc->mem_index = cpu_mmu_index(cs, false);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002970 dc->flags_uptodate = 1;
Richard Henderson330ca142021-06-19 20:49:26 -07002971 dc->flags_x = tb_flags & X_FLAG;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002972 dc->cc_x_uptodate = 0;
2973 dc->cc_mask = 0;
2974 dc->update_cc = 0;
2975 dc->clear_prefix = 0;
Richard Henderson330ca142021-06-19 20:49:26 -07002976 dc->cpustate_changed = 0;
edgar_igl30abcfc2008-05-27 21:10:56 +00002977
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002978 cris_update_cc_op(dc, CC_OP_FLAGS, 4);
2979 dc->cc_size_uptodate = -1;
edgar_iglb41f7df2008-05-02 22:16:17 +00002980
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002981 /* Decode TB flags. */
Richard Henderson330ca142021-06-19 20:49:26 -07002982 dc->tb_flags = tb_flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG | PFIX_FLAG);
2983 dc->delayed_branch = !!(tb_flags & 7);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04002984 if (dc->delayed_branch) {
2985 dc->jmp = JMP_INDIRECT;
2986 } else {
2987 dc->jmp = JMP_NOJMP;
2988 }
Richard Henderson330ca142021-06-19 20:49:26 -07002989}
edgar_igl2a44f7f2008-06-06 11:23:28 +00002990
Richard Henderson330ca142021-06-19 20:49:26 -07002991static void cris_tr_tb_start(DisasContextBase *db, CPUState *cpu)
2992{
2993}
edgar_iglb41f7df2008-05-02 22:16:17 +00002994
Richard Henderson330ca142021-06-19 20:49:26 -07002995static void cris_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
2996{
2997 DisasContext *dc = container_of(dcbase, DisasContext, base);
pbrook2e70f6e2008-06-29 01:03:05 +00002998
Richard Henderson330ca142021-06-19 20:49:26 -07002999 tcg_gen_insn_start(dc->delayed_branch == 1 ? dc->ppc | 1 : dc->pc);
3000}
edgar_iglcf1d97f2008-05-13 10:59:14 +00003001
Richard Henderson330ca142021-06-19 20:49:26 -07003002static void cris_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
3003{
3004 DisasContext *dc = container_of(dcbase, DisasContext, base);
Richard Henderson330ca142021-06-19 20:49:26 -07003005 unsigned int insn_len;
3006
3007 /* Pretty disas. */
3008 LOG_DIS("%8.8x:\t", dc->pc);
3009
3010 dc->clear_x = 1;
3011
Philippe Mathieu-Daudé2df4ab22024-01-29 17:44:52 +01003012 insn_len = dc->decoder(cpu_env(cs), dc);
Richard Henderson330ca142021-06-19 20:49:26 -07003013 dc->ppc = dc->pc;
3014 dc->pc += insn_len;
3015 dc->base.pc_next += insn_len;
3016
3017 if (dc->base.is_jmp == DISAS_NORETURN) {
3018 return;
3019 }
3020
3021 if (dc->clear_x) {
3022 cris_clear_x_flag(dc);
3023 }
3024
3025 /*
Richard Henderson31737152021-06-20 13:43:35 -07003026 * All branches are delayed branches, handled immediately below.
3027 * We don't expect to see odd combinations of exit conditions.
Richard Henderson330ca142021-06-19 20:49:26 -07003028 */
Richard Henderson31737152021-06-20 13:43:35 -07003029 assert(dc->base.is_jmp == DISAS_NEXT || dc->cpustate_changed);
3030
Richard Henderson330ca142021-06-19 20:49:26 -07003031 if (dc->delayed_branch && --dc->delayed_branch == 0) {
Richard Henderson31737152021-06-20 13:43:35 -07003032 dc->base.is_jmp = DISAS_DBRANCH;
3033 return;
3034 }
Richard Henderson330ca142021-06-19 20:49:26 -07003035
Richard Henderson31737152021-06-20 13:43:35 -07003036 if (dc->base.is_jmp != DISAS_NEXT) {
3037 return;
Richard Henderson330ca142021-06-19 20:49:26 -07003038 }
Richard Hendersonb9330662015-09-17 15:58:10 -07003039
Richard Henderson330ca142021-06-19 20:49:26 -07003040 /* Force an update if the per-tb cpu state has changed. */
Richard Henderson31737152021-06-20 13:43:35 -07003041 if (dc->cpustate_changed) {
Richard Hendersonc9674752021-06-22 07:50:12 -07003042 dc->base.is_jmp = DISAS_UPDATE_NEXT;
3043 return;
Richard Henderson330ca142021-06-19 20:49:26 -07003044 }
ths81700282007-10-08 12:49:08 +00003045
Richard Henderson330ca142021-06-19 20:49:26 -07003046 /*
3047 * FIXME: Only the first insn in the TB should cross a page boundary.
3048 * If we can detect the length of the next insn easily, we should.
3049 * In the meantime, simply stop when we do cross.
3050 */
Richard Henderson31737152021-06-20 13:43:35 -07003051 if ((dc->pc ^ dc->base.pc_first) & TARGET_PAGE_MASK) {
Richard Henderson330ca142021-06-19 20:49:26 -07003052 dc->base.is_jmp = DISAS_TOO_MANY;
3053 }
3054}
edgar_igl28de16d2008-09-22 20:51:28 +00003055
Richard Henderson330ca142021-06-19 20:49:26 -07003056static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
3057{
3058 DisasContext *dc = container_of(dcbase, DisasContext, base);
3059 DisasJumpType is_jmp = dc->base.is_jmp;
3060 target_ulong npc = dc->pc;
ths81700282007-10-08 12:49:08 +00003061
Richard Henderson330ca142021-06-19 20:49:26 -07003062 if (is_jmp == DISAS_NORETURN) {
3063 /* If we have a broken branch+delayslot sequence, it's too late. */
3064 assert(dc->delayed_branch != 1);
3065 return;
3066 }
edgar_iglb41f7df2008-05-02 22:16:17 +00003067
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003068 if (dc->clear_locked_irq) {
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01003069 t_gen_movi_env_TN(locked_irq, 0);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003070 }
Edgar E. Iglesias40e9edd2010-02-15 12:18:57 +01003071
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003072 /* Broken branch+delayslot sequence. */
3073 if (dc->delayed_branch == 1) {
3074 /* Set env->dslot to the size of the branch insn. */
Stefan Sandstromfd52dee2021-02-19 13:44:16 +01003075 t_gen_movi_env_TN(dslot, dc->pc - dc->ppc);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003076 cris_store_direct_jmp(dc);
3077 }
ths81700282007-10-08 12:49:08 +00003078
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003079 cris_evaluate_flags(dc);
edgar_igl2a44f7f2008-06-06 11:23:28 +00003080
Richard Henderson31737152021-06-20 13:43:35 -07003081 /* Evaluate delayed branch destination and fold to another is_jmp case. */
3082 if (is_jmp == DISAS_DBRANCH) {
3083 if (dc->base.tb->flags & 7) {
3084 t_gen_movi_env_TN(dslot, 0);
3085 }
3086
3087 switch (dc->jmp) {
3088 case JMP_DIRECT:
3089 npc = dc->jmp_pc;
3090 is_jmp = dc->cpustate_changed ? DISAS_UPDATE_NEXT : DISAS_TOO_MANY;
3091 break;
3092
3093 case JMP_DIRECT_CC:
3094 /*
3095 * Use a conditional branch if either taken or not-taken path
3096 * can use goto_tb. If neither can, then treat it as indirect.
3097 */
Richard Hendersonca92d7f2021-06-20 16:05:53 -07003098 if (likely(!dc->cpustate_changed)
Richard Henderson31737152021-06-20 13:43:35 -07003099 && (use_goto_tb(dc, dc->jmp_pc) || use_goto_tb(dc, npc))) {
3100 TCGLabel *not_taken = gen_new_label();
3101
3102 tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, not_taken);
3103 gen_goto_tb(dc, 1, dc->jmp_pc);
3104 gen_set_label(not_taken);
3105
3106 /* not-taken case handled below. */
3107 is_jmp = DISAS_TOO_MANY;
3108 break;
3109 }
3110 tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
3111 /* fall through */
3112
3113 case JMP_INDIRECT:
Richard Henderson3a1a80c2021-06-20 14:06:01 -07003114 tcg_gen_movcond_tl(TCG_COND_NE, env_pc,
3115 env_btaken, tcg_constant_tl(0),
3116 env_btarget, tcg_constant_tl(npc));
Richard Henderson31737152021-06-20 13:43:35 -07003117 is_jmp = dc->cpustate_changed ? DISAS_UPDATE : DISAS_JUMP;
Richard Henderson3a1a80c2021-06-20 14:06:01 -07003118
3119 /*
3120 * We have now consumed btaken and btarget. Hint to the
3121 * tcg compiler that the writeback to env may be dropped.
3122 */
3123 tcg_gen_discard_tl(env_btaken);
3124 tcg_gen_discard_tl(env_btarget);
Richard Henderson31737152021-06-20 13:43:35 -07003125 break;
3126
3127 default:
3128 g_assert_not_reached();
3129 }
3130 }
3131
Richard Henderson330ca142021-06-19 20:49:26 -07003132 switch (is_jmp) {
3133 case DISAS_TOO_MANY:
3134 gen_goto_tb(dc, 0, npc);
3135 break;
Richard Hendersonc9674752021-06-22 07:50:12 -07003136 case DISAS_UPDATE_NEXT:
3137 tcg_gen_movi_tl(env_pc, npc);
3138 /* fall through */
Richard Henderson330ca142021-06-19 20:49:26 -07003139 case DISAS_JUMP:
Richard Hendersone0a46202021-06-20 13:49:17 -07003140 tcg_gen_lookup_and_goto_ptr();
3141 break;
Richard Henderson330ca142021-06-19 20:49:26 -07003142 case DISAS_UPDATE:
Michael Tokarev8b819682023-07-14 14:23:51 +03003143 /* Indicate that interrupts must be re-evaluated before the next TB. */
Richard Henderson330ca142021-06-19 20:49:26 -07003144 tcg_gen_exit_tb(NULL, 0);
3145 break;
3146 default:
3147 g_assert_not_reached();
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003148 }
Richard Henderson330ca142021-06-19 20:49:26 -07003149}
3150
Richard Henderson8eb806a2022-04-17 11:29:52 -07003151static void cris_tr_disas_log(const DisasContextBase *dcbase,
3152 CPUState *cpu, FILE *logfile)
Richard Henderson330ca142021-06-19 20:49:26 -07003153{
3154 if (!DISAS_CRIS) {
Richard Henderson8eb806a2022-04-17 11:29:52 -07003155 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
3156 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
Richard Henderson330ca142021-06-19 20:49:26 -07003157 }
3158}
3159
3160static const TranslatorOps cris_tr_ops = {
3161 .init_disas_context = cris_tr_init_disas_context,
3162 .tb_start = cris_tr_tb_start,
3163 .insn_start = cris_tr_insn_start,
Richard Henderson330ca142021-06-19 20:49:26 -07003164 .translate_insn = cris_tr_translate_insn,
3165 .tb_stop = cris_tr_tb_stop,
3166 .disas_log = cris_tr_disas_log,
3167};
3168
Richard Henderson597f9b22023-01-28 15:19:22 -10003169void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
Anton Johansson32f0c392024-01-19 15:39:58 +01003170 vaddr pc, void *host_pc)
Richard Henderson330ca142021-06-19 20:49:26 -07003171{
3172 DisasContext dc;
Richard Henderson306c8722022-08-11 13:48:03 -07003173 translator_loop(cs, tb, max_insns, pc, host_pc, &cris_tr_ops, &dc.base);
ths81700282007-10-08 12:49:08 +00003174}
3175
Markus Armbruster90c84c52019-04-17 21:18:02 +02003176void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags)
ths81700282007-10-08 12:49:08 +00003177{
Philippe Mathieu-Daudé2df4ab22024-01-29 17:44:52 +01003178 CPUCRISState *env = cpu_env(cs);
Richard Henderson5899ce62021-06-19 20:57:31 -07003179 const char * const *regnames;
3180 const char * const *pregnames;
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003181 int i;
ths81700282007-10-08 12:49:08 +00003182
Markus Armbruster90c84c52019-04-17 21:18:02 +02003183 if (!env) {
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003184 return;
3185 }
Hans-Peter Nilsson17bc37b72016-08-15 13:44:46 +02003186 if (env->pregs[PR_VR] < 32) {
3187 pregnames = pregnames_v10;
3188 regnames = regnames_v10;
3189 } else {
3190 pregnames = pregnames_v32;
3191 regnames = regnames_v32;
3192 }
ths81700282007-10-08 12:49:08 +00003193
Markus Armbruster90c84c52019-04-17 21:18:02 +02003194 qemu_fprintf(f, "PC=%x CCS=%x btaken=%d btarget=%x\n"
3195 "cc_op=%d cc_src=%d cc_dest=%d cc_result=%x cc_mask=%x\n",
3196 env->pc, env->pregs[PR_CCS], env->btaken, env->btarget,
3197 env->cc_op,
3198 env->cc_src, env->cc_dest, env->cc_result, env->cc_mask);
edgar_igl30abcfc2008-05-27 21:10:56 +00003199
ths81700282007-10-08 12:49:08 +00003200
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003201 for (i = 0; i < 16; i++) {
Markus Armbruster90c84c52019-04-17 21:18:02 +02003202 qemu_fprintf(f, "%s=%8.8x ", regnames[i], env->regs[i]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003203 if ((i + 1) % 4 == 0) {
Markus Armbruster90c84c52019-04-17 21:18:02 +02003204 qemu_fprintf(f, "\n");
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003205 }
3206 }
Markus Armbruster90c84c52019-04-17 21:18:02 +02003207 qemu_fprintf(f, "\nspecial regs:\n");
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003208 for (i = 0; i < 16; i++) {
Markus Armbruster90c84c52019-04-17 21:18:02 +02003209 qemu_fprintf(f, "%s=%8.8x ", pregnames[i], env->pregs[i]);
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003210 if ((i + 1) % 4 == 0) {
Markus Armbruster90c84c52019-04-17 21:18:02 +02003211 qemu_fprintf(f, "\n");
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003212 }
3213 }
Hans-Peter Nilsson17bc37b72016-08-15 13:44:46 +02003214 if (env->pregs[PR_VR] >= 32) {
3215 uint32_t srs = env->pregs[PR_SRS];
Markus Armbruster90c84c52019-04-17 21:18:02 +02003216 qemu_fprintf(f, "\nsupport function regs bank %x:\n", srs);
Hans-Peter Nilsson17bc37b72016-08-15 13:44:46 +02003217 if (srs < ARRAY_SIZE(env->sregs)) {
3218 for (i = 0; i < 16; i++) {
Markus Armbruster90c84c52019-04-17 21:18:02 +02003219 qemu_fprintf(f, "s%2.2d=%8.8x ",
3220 i, env->sregs[srs][i]);
Hans-Peter Nilsson17bc37b72016-08-15 13:44:46 +02003221 if ((i + 1) % 4 == 0) {
Markus Armbruster90c84c52019-04-17 21:18:02 +02003222 qemu_fprintf(f, "\n");
Hans-Peter Nilsson17bc37b72016-08-15 13:44:46 +02003223 }
Evgeny Voevodin7b5eff42012-11-12 13:27:43 +04003224 }
3225 }
3226 }
Markus Armbruster90c84c52019-04-17 21:18:02 +02003227 qemu_fprintf(f, "\n\n");
ths81700282007-10-08 12:49:08 +00003228
3229}
3230
Andreas Färberd1a94fe2013-01-19 23:55:42 +01003231void cris_initialize_tcg(void)
3232{
3233 int i;
edgar_igl05ba7d52008-03-14 01:11:25 +00003234
Richard Hendersonad75a512023-09-13 16:37:36 -07003235 cc_x = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003236 offsetof(CPUCRISState, cc_x), "cc_x");
Richard Hendersonad75a512023-09-13 16:37:36 -07003237 cc_src = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003238 offsetof(CPUCRISState, cc_src), "cc_src");
Richard Hendersonad75a512023-09-13 16:37:36 -07003239 cc_dest = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003240 offsetof(CPUCRISState, cc_dest),
3241 "cc_dest");
Richard Hendersonad75a512023-09-13 16:37:36 -07003242 cc_result = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003243 offsetof(CPUCRISState, cc_result),
3244 "cc_result");
Richard Hendersonad75a512023-09-13 16:37:36 -07003245 cc_op = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003246 offsetof(CPUCRISState, cc_op), "cc_op");
Richard Hendersonad75a512023-09-13 16:37:36 -07003247 cc_size = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003248 offsetof(CPUCRISState, cc_size),
3249 "cc_size");
Richard Hendersonad75a512023-09-13 16:37:36 -07003250 cc_mask = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003251 offsetof(CPUCRISState, cc_mask),
3252 "cc_mask");
edgar_igla825e702008-03-16 16:51:58 +00003253
Richard Hendersonad75a512023-09-13 16:37:36 -07003254 env_pc = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003255 offsetof(CPUCRISState, pc),
3256 "pc");
Richard Hendersonad75a512023-09-13 16:37:36 -07003257 env_btarget = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003258 offsetof(CPUCRISState, btarget),
3259 "btarget");
Richard Hendersonad75a512023-09-13 16:37:36 -07003260 env_btaken = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003261 offsetof(CPUCRISState, btaken),
3262 "btaken");
3263 for (i = 0; i < 16; i++) {
Richard Hendersonad75a512023-09-13 16:37:36 -07003264 cpu_R[i] = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003265 offsetof(CPUCRISState, regs[i]),
Hans-Peter Nilsson17bc37b72016-08-15 13:44:46 +02003266 regnames_v32[i]);
Andreas Färberdd10ce62012-05-05 11:45:32 +02003267 }
3268 for (i = 0; i < 16; i++) {
Richard Hendersonad75a512023-09-13 16:37:36 -07003269 cpu_PR[i] = tcg_global_mem_new(tcg_env,
Andreas Färberdd10ce62012-05-05 11:45:32 +02003270 offsetof(CPUCRISState, pregs[i]),
Hans-Peter Nilsson17bc37b72016-08-15 13:44:46 +02003271 pregnames_v32[i]);
Andreas Färberdd10ce62012-05-05 11:45:32 +02003272 }
ths81700282007-10-08 12:49:08 +00003273}