• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revision297644bdb366ac886f6005b52f64423b89073df7 (tree)
Time2019-09-12 12:01:49
AuthorYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Log Message

target/rx: TCG translation

This part only supported RXv1 instructions.
Instruction manual.
https://www.renesas.com/us/en/doc/products/mpumcu/doc/rx_family/r01us0032ej0120_rxsm.pdf

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190607091116.49044-2-ysato@users.sourceforge.jp>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Change Summary

Incremental Difference

--- /dev/null
+++ b/target/rx/Makefile.objs
@@ -0,0 +1,12 @@
1+obj-y += translate.o op_helper.o helper.o cpu.o gdbstub.o disas.o
2+obj-$(CONFIG_SOFTMMU) += monitor.o
3+
4+DECODETREE = $(SRC_PATH)/scripts/decodetree.py
5+
6+target/rx/decode.inc.c: \
7+ $(SRC_PATH)/target/rx/insns.decode $(DECODETREE)
8+ $(call quiet-command,\
9+ $(PYTHON) $(DECODETREE) --varinsnwidth 32 -o $@ $<, "GEN", $(TARGET_DIR)$@)
10+
11+target/rx/translate.o: target/rx/decode.inc.c
12+target/rx/disas.o: target/rx/decode.inc.c
--- /dev/null
+++ b/target/rx/insns.decode
@@ -0,0 +1,621 @@
1+#
2+# Renesas RX instruction decode definitions.
3+#
4+# Copyright (c) 2019 Richard Henderson <richard.henderson@linaro.org>
5+# Copyright (c) 2019 Yoshinori Sato <ysato@users.sourceforge.jp>
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
10+# version 2 of the License, or (at your option) any later version.
11+#
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
18+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
19+#
20+
21+&bcnd cd dsp sz
22+&jdsp dsp sz
23+&jreg rs
24+&rr rd rs
25+&ri rd imm
26+&rrr rd rs rs2
27+&rri rd imm rs2
28+&rm rd rs ld mi
29+&mi rs ld mi imm
30+&mr rs ld mi rs2
31+&mcnd ld sz rd cd
32+########
33+%b1_bdsp 24:3 !function=bdsp_s
34+
35+@b1_bcnd_s .... cd:1 ... &bcnd dsp=%b1_bdsp sz=1
36+@b1_bra_s .... .... &jdsp dsp=%b1_bdsp sz=1
37+
38+%b2_r_0 16:4
39+%b2_li_2 18:2 !function=li
40+%b2_li_8 24:2 !function=li
41+%b2_dsp5_3 23:4 19:1
42+
43+@b2_rds .... .... .... rd:4 &rr rs=%b2_r_0
44+@b2_rds_li .... .... .... rd:4 &rri rs2=%b2_r_0 imm=%b2_li_8
45+@b2_rds_uimm4 .... .... imm:4 rd:4 &rri rs2=%b2_r_0
46+@b2_rs2_uimm4 .... .... imm:4 rs2:4 &rri rd=0
47+@b2_rds_imm5 .... ... imm:5 rd:4 &rri rs2=%b2_r_0
48+@b2_rd_rs_li .... .... rs2:4 rd:4 &rri imm=%b2_li_8
49+@b2_rd_ld_ub .... .. ld:2 rs:4 rd:4 &rm mi=4
50+@b2_ld_imm3 .... .. ld:2 rs:4 . imm:3 &mi mi=4
51+@b2_bcnd_b .... cd:4 dsp:s8 &bcnd sz=2
52+@b2_bra_b .... .... dsp:s8 &jdsp sz=2
53+
54+########
55+
56+%b3_r_0 8:4
57+%b3_li_10 18:2 !function=li
58+%b3_dsp5_8 23:1 16:4
59+%b3_bdsp 8:s8 16:8
60+
61+@b3_rd_rs .... .... .... .... rs:4 rd:4 &rr
62+@b3_rs_rd .... .... .... .... rd:4 rs:4 &rr
63+@b3_rd_li .... .... .... .... .... rd:4 \
64+ &rri rs2=%b3_r_0 imm=%b3_li_10
65+@b3_rd_ld .... .... mi:2 .... ld:2 rs:4 rd:4 &rm
66+@b3_rd_ld_ub .... .... .... .. ld:2 rs:4 rd:4 &rm mi=4
67+@b3_rd_ld_ul .... .... .... .. ld:2 rs:4 rd:4 &rm mi=2
68+@b3_rd_rs_rs2 .... .... .... rd:4 rs:4 rs2:4 &rrr
69+@b3_rds_imm5 .... .... ....... imm:5 rd:4 &rri rs2=%b3_r_0
70+@b3_rd_rs_imm5 .... .... ... imm:5 rs2:4 rd:4 &rri
71+@b3_bcnd_w .... ... cd:1 .... .... .... .... &bcnd dsp=%b3_bdsp sz=3
72+@b3_bra_w .... .... .... .... .... .... &jdsp dsp=%b3_bdsp sz=3
73+@b3_ld_rd_rs .... .... .... .. ld:2 rs:4 rd:4 &rm mi=0
74+@b3_sz_ld_rd_cd .... .... .... sz:2 ld:2 rd:4 cd:4 &mcnd
75+
76+########
77+
78+%b4_li_18 18:2 !function=li
79+%b4_dsp_16 0:s8 8:8
80+%b4_bdsp 0:s8 8:8 16:8
81+
82+@b4_rd_ldmi .... .... mi:2 .... ld:2 .... .... rs:4 rd:4 &rm
83+@b4_bra_a .... .... .... .... .... .... .... .... \
84+ &jdsp dsp=%b4_bdsp sz=4
85+########
86+# ABS rd
87+ABS_rr 0111 1110 0010 .... @b2_rds
88+# ABS rs, rd
89+ABS_rr 1111 1100 0000 1111 .... .... @b3_rd_rs
90+
91+# ADC #imm, rd
92+ADC_ir 1111 1101 0111 ..00 0010 .... @b3_rd_li
93+# ADC rs, rd
94+ADC_rr 1111 1100 0000 1011 .... .... @b3_rd_rs
95+# ADC dsp[rs].l, rd
96+# Note only mi==2 allowed.
97+ADC_mr 0000 0110 ..10 00.. 0000 0010 .... .... @b4_rd_ldmi
98+
99+# ADD #uimm4, rd
100+ADD_irr 0110 0010 .... .... @b2_rds_uimm4
101+# ADD #imm, rs, rd
102+ADD_irr 0111 00.. .... .... @b2_rd_rs_li
103+# ADD dsp[rs].ub, rd
104+# ADD rs, rd
105+ADD_mr 0100 10.. .... .... @b2_rd_ld_ub
106+# ADD dsp[rs], rd
107+ADD_mr 0000 0110 ..00 10.. .... .... @b3_rd_ld
108+# ADD rs, rs2, rd
109+ADD_rrr 1111 1111 0010 .... .... .... @b3_rd_rs_rs2
110+
111+# AND #uimm4, rd
112+AND_ir 0110 0100 .... .... @b2_rds_uimm4
113+# AND #imm, rd
114+AND_ir 0111 01.. 0010 .... @b2_rds_li
115+# AND dsp[rs].ub, rd
116+# AND rs, rd
117+AND_mr 0101 00.. .... .... @b2_rd_ld_ub
118+# AND dsp[rs], rd
119+AND_mr 0000 0110 ..01 00.. .... .... @b3_rd_ld
120+# AND rs, rs2, rd
121+AND_rrr 1111 1111 0100 .... .... .... @b3_rd_rs_rs2
122+
123+# BCLR #imm, dsp[rd]
124+BCLR_im 1111 00.. .... 1... @b2_ld_imm3
125+# BCLR #imm, rs
126+BCLR_ir 0111 101. .... .... @b2_rds_imm5
127+# BCLR rs, rd
128+# BCLR rs, dsp[rd]
129+{
130+ BCLR_rr 1111 1100 0110 0111 .... .... @b3_rs_rd
131+ BCLR_rm 1111 1100 0110 01.. .... .... @b3_rd_ld_ub
132+}
133+
134+# BCnd.s dsp
135+BCnd 0001 .... @b1_bcnd_s
136+# BRA.b dsp
137+# BCnd.b dsp
138+{
139+ BRA 0010 1110 .... .... @b2_bra_b
140+ BCnd 0010 .... .... .... @b2_bcnd_b
141+}
142+
143+# BCnd.w dsp
144+BCnd 0011 101 . .... .... .... .... @b3_bcnd_w
145+
146+# BNOT #imm, dsp[rd]
147+# BMCnd #imm, dsp[rd]
148+{
149+ BNOT_im 1111 1100 111 imm:3 ld:2 rs:4 1111
150+ BMCnd_im 1111 1100 111 imm:3 ld:2 rd:4 cd:4
151+}
152+
153+# BNOT #imm, rd
154+# BMCnd #imm, rd
155+{
156+ BNOT_ir 1111 1101 111 imm:5 1111 rd:4
157+ BMCnd_ir 1111 1101 111 imm:5 cd:4 rd:4
158+}
159+
160+# BNOT rs, rd
161+# BNOT rs, dsp[rd]
162+{
163+ BNOT_rr 1111 1100 0110 1111 .... .... @b3_rs_rd
164+ BNOT_rm 1111 1100 0110 11.. .... .... @b3_rd_ld_ub
165+}
166+
167+# BRA.s dsp
168+BRA 0000 1 ... @b1_bra_s
169+# BRA.w dsp
170+BRA 0011 1000 .... .... .... .... @b3_bra_w
171+# BRA.a dsp
172+BRA 0000 0100 .... .... .... .... .... .... @b4_bra_a
173+# BRA.l rs
174+BRA_l 0111 1111 0100 rd:4
175+
176+BRK 0000 0000
177+
178+# BSET #imm, dsp[rd]
179+BSET_im 1111 00.. .... 0... @b2_ld_imm3
180+# BSET #imm, rd
181+BSET_ir 0111 100. .... .... @b2_rds_imm5
182+# BSET rs, rd
183+# BSET rs, dsp[rd]
184+{
185+ BSET_rr 1111 1100 0110 0011 .... .... @b3_rs_rd
186+ BSET_rm 1111 1100 0110 00.. .... .... @b3_rd_ld_ub
187+}
188+
189+# BSR.w dsp
190+BSR 0011 1001 .... .... .... .... @b3_bra_w
191+# BSR.a dsp
192+BSR 0000 0101 .... .... .... .... .... .... @b4_bra_a
193+# BSR.l rs
194+BSR_l 0111 1111 0101 rd:4
195+
196+# BSET #imm, dsp[rd]
197+BTST_im 1111 01.. .... 0... @b2_ld_imm3
198+# BSET #imm, rd
199+BTST_ir 0111 110. .... .... @b2_rds_imm5
200+# BSET rs, rd
201+# BSET rs, dsp[rd]
202+{
203+ BTST_rr 1111 1100 0110 1011 .... .... @b3_rs_rd
204+ BTST_rm 1111 1100 0110 10.. .... .... @b3_rd_ld_ub
205+}
206+
207+# CLRSPW psw
208+CLRPSW 0111 1111 1011 cb:4
209+
210+# CMP #uimm4, rs2
211+CMP_ir 0110 0001 .... .... @b2_rs2_uimm4
212+# CMP #uimm8, rs2
213+CMP_ir 0111 0101 0101 rs2:4 imm:8 &rri rd=0
214+# CMP #imm, rs2
215+CMP_ir 0111 01.. 0000 rs2:4 &rri imm=%b2_li_8 rd=0
216+# CMP dsp[rs].ub, rs2
217+# CMP rs, rs2
218+CMP_mr 0100 01.. .... .... @b2_rd_ld_ub
219+# CMP dsp[rs], rs2
220+CMP_mr 0000 0110 ..00 01.. .... .... @b3_rd_ld
221+
222+# DIV #imm, rd
223+DIV_ir 1111 1101 0111 ..00 1000 .... @b3_rd_li
224+# DIV dsp[rs].ub, rd
225+# DIV rs, rd
226+DIV_mr 1111 1100 0010 00.. .... .... @b3_rd_ld_ub
227+# DIV dsp[rs], rd
228+DIV_mr 0000 0110 ..10 00.. 0000 1000 .... .... @b4_rd_ldmi
229+
230+# DIVU #imm, rd
231+DIVU_ir 1111 1101 0111 ..00 1001 .... @b3_rd_li
232+# DIVU dsp[rs].ub, rd
233+# DIVU rs, rd
234+DIVU_mr 1111 1100 0010 01.. .... .... @b3_rd_ld_ub
235+# DIVU dsp[rs], rd
236+DIVU_mr 0000 0110 ..10 00.. 0000 1001 .... .... @b4_rd_ldmi
237+
238+# EMUL #imm, rd
239+EMUL_ir 1111 1101 0111 ..00 0110 .... @b3_rd_li
240+# EMUL dsp[rs].ub, rd
241+# EMUL rs, rd
242+EMUL_mr 1111 1100 0001 10.. .... .... @b3_rd_ld_ub
243+# EMUL dsp[rs], rd
244+EMUL_mr 0000 0110 ..10 00.. 0000 0110 .... .... @b4_rd_ldmi
245+
246+# EMULU #imm, rd
247+EMULU_ir 1111 1101 0111 ..00 0111 .... @b3_rd_li
248+# EMULU dsp[rs].ub, rd
249+# EMULU rs, rd
250+EMULU_mr 1111 1100 0001 11.. .... .... @b3_rd_ld_ub
251+# EMULU dsp[rs], rd
252+EMULU_mr 0000 0110 ..10 00.. 0000 0111 .... .... @b4_rd_ldmi
253+
254+# FADD #imm, rd
255+FADD_ir 1111 1101 0111 0010 0010 rd:4
256+# FADD rs, rd
257+# FADD dsp[rs], rd
258+FADD_mr 1111 1100 1000 10.. .... .... @b3_rd_ld_ul
259+
260+# FCMP #imm, rd
261+FCMP_ir 1111 1101 0111 0010 0001 rd:4
262+# FCMP rs, rd
263+# FCMP dsp[rs], rd
264+FCMP_mr 1111 1100 1000 01.. .... .... @b3_rd_ld_ul
265+
266+# FDIV #imm, rd
267+FDIV_ir 1111 1101 0111 0010 0100 rd:4
268+# FDIV rs, rd
269+# FDIV dsp[rs], rd
270+FDIV_mr 1111 1100 1001 00.. .... .... @b3_rd_ld_ul
271+
272+# FMUL #imm, rd
273+FMUL_ir 1111 1101 0111 0010 0011 rd:4
274+# FMUL rs, rd
275+# FMUL dsp[rs], rd
276+FMUL_mr 1111 1100 1000 11.. .... .... @b3_rd_ld_ul
277+
278+# FSUB #imm, rd
279+FSUB_ir 1111 1101 0111 0010 0000 rd:4
280+# FSUB rs, rd
281+# FSUB dsp[rs], rd
282+FSUB_mr 1111 1100 1000 00.. .... .... @b3_rd_ld_ul
283+
284+# FTOI rs, rd
285+# FTOI dsp[rs], rd
286+FTOI 1111 1100 1001 01.. .... .... @b3_rd_ld_ul
287+
288+# INT #uimm8
289+INT 0111 0101 0110 0000 imm:8
290+
291+# ITOF dsp[rs].ub, rd
292+# ITOF rs, rd
293+ITOF 1111 1100 0100 01.. .... .... @b3_rd_ld_ub
294+# ITOF dsp[rs], rd
295+ITOF 0000 0110 ..10 00.. 0001 0001 .... .... @b4_rd_ldmi
296+
297+# JMP rs
298+JMP 0111 1111 0000 rs:4 &jreg
299+# JSR rs
300+JSR 0111 1111 0001 rs:4 &jreg
301+
302+# MACHI rs, rs2
303+MACHI 1111 1101 0000 0100 rs:4 rs2:4
304+# MACLO rs, rs2
305+MACLO 1111 1101 0000 0101 rs:4 rs2:4
306+
307+# MAX #imm, rd
308+MAX_ir 1111 1101 0111 ..00 0100 .... @b3_rd_li
309+# MAX dsp[rs].ub, rd
310+# MAX rs, rd
311+MAX_mr 1111 1100 0001 00.. .... .... @b3_rd_ld_ub
312+# MAX dsp[rs], rd
313+MAX_mr 0000 0110 ..10 00.. 0000 0100 .... .... @b4_rd_ldmi
314+
315+# MIN #imm, rd
316+MIN_ir 1111 1101 0111 ..00 0101 .... @b3_rd_li
317+# MIN dsp[rs].ub, rd
318+# MIN rs, rd
319+MIN_mr 1111 1100 0001 01.. .... .... @b3_rd_ld_ub
320+# MIN dsp[rs], rd
321+MIN_mr 0000 0110 ..10 00.. 0000 0101 .... .... @b4_rd_ldmi
322+
323+# MOV.b rs, dsp5[rd]
324+MOV_rm 1000 0 .... rd:3 . rs:3 dsp=%b2_dsp5_3 sz=0
325+# MOV.w rs, dsp5[rd]
326+MOV_rm 1001 0 .... rd:3 . rs:3 dsp=%b2_dsp5_3 sz=1
327+# MOV.l rs, dsp5[rd]
328+MOV_rm 1010 0 .... rd:3 . rs:3 dsp=%b2_dsp5_3 sz=2
329+# MOV.b dsp5[rs], rd
330+MOV_mr 1000 1 .... rs:3 . rd:3 dsp=%b2_dsp5_3 sz=0
331+# MOV.w dsp5[rs], rd
332+MOV_mr 1001 1 .... rs:3 . rd:3 dsp=%b2_dsp5_3 sz=1
333+# MOV.l dsp5[rs], rd
334+MOV_mr 1010 1 .... rs:3 . rd:3 dsp=%b2_dsp5_3 sz=2
335+# MOV.l #uimm4, rd
336+MOV_ir 0110 0110 imm:4 rd:4
337+# MOV.b #imm8, dsp5[rd]
338+MOV_im 0011 1100 . rd:3 .... imm:8 sz=0 dsp=%b3_dsp5_8
339+# MOV.w #imm8, dsp5[rd]
340+MOV_im 0011 1101 . rd:3 .... imm:8 sz=1 dsp=%b3_dsp5_8
341+# MOV.l #imm8, dsp5[rd]
342+MOV_im 0011 1110 . rd:3 .... imm:8 sz=2 dsp=%b3_dsp5_8
343+# MOV.l #imm8, rd
344+MOV_ir 0111 0101 0100 rd:4 imm:8
345+# MOV.l #mm8, rd
346+MOV_ir 1111 1011 rd:4 .. 10 imm=%b2_li_2
347+# MOV.<bwl> #imm, [rd]
348+MOV_im 1111 1000 rd:4 .. sz:2 dsp=0 imm=%b2_li_2
349+# MOV.<bwl> #imm, dsp8[rd]
350+MOV_im 1111 1001 rd:4 .. sz:2 dsp:8 imm=%b3_li_10
351+# MOV.<bwl> #imm, dsp16[rd]
352+MOV_im 1111 1010 rd:4 .. sz:2 .... .... .... .... \
353+ imm=%b4_li_18 dsp=%b4_dsp_16
354+# MOV.<bwl> [ri,rb], rd
355+MOV_ar 1111 1110 01 sz:2 ri:4 rb:4 rd:4
356+# MOV.<bwl> rs, [ri,rb]
357+MOV_ra 1111 1110 00 sz:2 ri:4 rb:4 rs:4
358+# Note ldd=3 and lds=3 indicate register src or dst
359+# MOV.b rs, rd
360+# MOV.b rs, dsp[rd]
361+# MOV.b dsp[rs], rd
362+# MOV.b dsp[rs], dsp[rd]
363+MOV_mm 1100 ldd:2 lds:2 rs:4 rd:4 sz=0
364+# MOV.w rs, rd
365+# MOV.w rs, dsp[rd]
366+# MOV.w dsp[rs], rd
367+# MOV.w dsp[rs], dsp[rd]
368+MOV_mm 1101 ldd:2 lds:2 rs:4 rd:4 sz=1
369+# MOV.l rs, rd
370+# MOV.l rs, dsp[rd]
371+# MOV.l dsp[rs], rd
372+# MOV.l dsp[rs], dsp[rd]
373+MOV_mm 1110 ldd:2 lds:2 rs:4 rd:4 sz=2
374+# MOV.l rs, [rd+]
375+# MOV.l rs, [-rd]
376+MOV_rp 1111 1101 0010 0 ad:1 sz:2 rd:4 rs:4
377+# MOV.l [rs+], rd
378+# MOV.l [-rs], rd
379+MOV_pr 1111 1101 0010 1 ad:1 sz:2 rd:4 rs:4
380+
381+# MOVU.<bw> dsp5[rs], rd
382+MOVU_mr 1011 sz:1 ... . rs:3 . rd:3 dsp=%b2_dsp5_3
383+# MOVU.<bw> [rs], rd
384+MOVU_mr 0101 1 sz:1 00 rs:4 rd:4 dsp=0
385+# MOVU.<bw> dsp8[rs], rd
386+MOVU_mr 0101 1 sz:1 01 rs:4 rd:4 dsp:8
387+# MOVU.<bw> dsp16[rs], rd
388+MOVU_mr 0101 1 sz:1 10 rs:4 rd:4 .... .... .... .... dsp=%b4_dsp_16
389+# MOVU.<bw> rs, rd
390+MOVU_rr 0101 1 sz:1 11 rs:4 rd:4
391+# MOVU.<bw> [ri, rb], rd
392+MOVU_ar 1111 1110 110 sz:1 ri:4 rb:4 rd:4
393+# MOVU.<bw> [rs+], rd
394+MOVU_pr 1111 1101 0011 1 ad:1 0 sz:1 rd:4 rs:4
395+
396+# MUL #uimm4, rd
397+MUL_ir 0110 0011 .... .... @b2_rds_uimm4
398+# MUL #imm4, rd
399+MUL_ir 0111 01.. 0001 .... @b2_rds_li
400+# MUL dsp[rs].ub, rd
401+# MUL rs, rd
402+MUL_mr 0100 11.. .... .... @b2_rd_ld_ub
403+# MUL dsp[rs], rd
404+MUL_mr 0000 0110 ..00 11.. .... .... @b3_rd_ld
405+# MOV rs, rs2, rd
406+MUL_rrr 1111 1111 0011 .... .... .... @b3_rd_rs_rs2
407+
408+# MULHI rs, rs2
409+MULHI 1111 1101 0000 0000 rs:4 rs2:4
410+# MULLO rs, rs2
411+MULLO 1111 1101 0000 0001 rs:4 rs2:4
412+
413+# MVFACHI rd
414+MVFACHI 1111 1101 0001 1111 0000 rd:4
415+# MVFACMI rd
416+MVFACMI 1111 1101 0001 1111 0010 rd:4
417+
418+# MVFC cr, rd
419+MVFC 1111 1101 0110 1010 cr:4 rd:4
420+
421+# MVTACHI rs
422+MVTACHI 1111 1101 0001 0111 0000 rs:4
423+# MVTACLO rs
424+MVTACLO 1111 1101 0001 0111 0001 rs:4
425+
426+# MVTC #imm, cr
427+MVTC_i 1111 1101 0111 ..11 0000 cr:4 imm=%b3_li_10
428+# MVTC rs, cr
429+MVTC_r 1111 1101 0110 1000 rs:4 cr:4
430+
431+# MVTIPL #imm
432+MVTIPL 0111 0101 0111 0000 0000 imm:4
433+
434+# NEG rd
435+NEG_rr 0111 1110 0001 .... @b2_rds
436+# NEG rs, rd
437+NEG_rr 1111 1100 0000 0111 .... .... @b3_rd_rs
438+
439+NOP 0000 0011
440+
441+# NOT rd
442+NOT_rr 0111 1110 0000 .... @b2_rds
443+# NOT rs, rd
444+NOT_rr 1111 1100 0011 1011 .... .... @b3_rd_rs
445+
446+# OR #uimm4, rd
447+OR_ir 0110 0101 .... .... @b2_rds_uimm4
448+# OR #imm, rd
449+OR_ir 0111 01.. 0011 .... @b2_rds_li
450+# OR dsp[rs].ub, rd
451+# OR rs, rd
452+OR_mr 0101 01.. .... .... @b2_rd_ld_ub
453+# OR dsp[rs], rd
454+OR_mr 0000 0110 .. 0101 .. .... .... @b3_rd_ld
455+# OR rs, rs2, rd
456+OR_rrr 1111 1111 0101 .... .... .... @b3_rd_rs_rs2
457+
458+# POP cr
459+POPC 0111 1110 1110 cr:4
460+# POP rd-rd2
461+POPM 0110 1111 rd:4 rd2:4
462+
463+# POP rd
464+# PUSH.<bwl> rs
465+{
466+ POP 0111 1110 1011 rd:4
467+ PUSH_r 0111 1110 10 sz:2 rs:4
468+}
469+# PUSH.<bwl> dsp[rs]
470+PUSH_m 1111 01 ld:2 rs:4 10 sz:2
471+# PUSH cr
472+PUSHC 0111 1110 1100 cr:4
473+# PUSHM rs-rs2
474+PUSHM 0110 1110 rs:4 rs2:4
475+
476+# RACW #imm
477+RACW 1111 1101 0001 1000 000 imm:1 0000
478+
479+# REVL rs,rd
480+REVL 1111 1101 0110 0111 .... .... @b3_rd_rs
481+# REVW rs,rd
482+REVW 1111 1101 0110 0101 .... .... @b3_rd_rs
483+
484+# SMOVF
485+# RPMA.<bwl>
486+{
487+ SMOVF 0111 1111 1000 1111
488+ RMPA 0111 1111 1000 11 sz:2
489+}
490+
491+# ROLC rd
492+ROLC 0111 1110 0101 .... @b2_rds
493+# RORC rd
494+RORC 0111 1110 0100 .... @b2_rds
495+
496+# ROTL #imm, rd
497+ROTL_ir 1111 1101 0110 111. .... .... @b3_rds_imm5
498+# ROTL rs, rd
499+ROTL_rr 1111 1101 0110 0110 .... .... @b3_rd_rs
500+
501+# ROTR #imm, rd
502+ROTR_ir 1111 1101 0110 110. .... .... @b3_rds_imm5
503+# ROTR #imm, rd
504+ROTR_rr 1111 1101 0110 0100 .... .... @b3_rd_rs
505+
506+# ROUND rs,rd
507+# ROUND dsp[rs],rd
508+ROUND 1111 1100 1001 10 .. .... .... @b3_ld_rd_rs
509+
510+RTE 0111 1111 1001 0101
511+
512+RTFI 0111 1111 1001 0100
513+
514+RTS 0000 0010
515+
516+# RTSD #imm
517+RTSD_i 0110 0111 imm:8
518+# RTSD #imm, rd-rd2
519+RTSD_irr 0011 1111 rd:4 rd2:4 imm:8
520+
521+# SAT rd
522+SAT 0111 1110 0011 .... @b2_rds
523+# SATR
524+SATR 0111 1111 1001 0011
525+
526+# SBB rs, rd
527+SBB_rr 1111 1100 0000 0011 .... .... @b3_rd_rs
528+# SBB dsp[rs].l, rd
529+# Note only mi==2 allowed.
530+SBB_mr 0000 0110 ..10 00.. 0000 0000 .... .... @b4_rd_ldmi
531+
532+# SCCnd dsp[rd]
533+# SCCnd rd
534+SCCnd 1111 1100 1101 .... .... .... @b3_sz_ld_rd_cd
535+
536+# SETPSW psw
537+SETPSW 0111 1111 1010 cb:4
538+
539+# SHAR #imm, rd
540+SHAR_irr 0110 101. .... .... @b2_rds_imm5
541+# SHAR #imm, rs, rd
542+SHAR_irr 1111 1101 101. .... .... .... @b3_rd_rs_imm5
543+# SHAR rs, rd
544+SHAR_rr 1111 1101 0110 0001 .... .... @b3_rd_rs
545+
546+# SHLL #imm, rd
547+SHLL_irr 0110 110. .... .... @b2_rds_imm5
548+# SHLL #imm, rs, rd
549+SHLL_irr 1111 1101 110. .... .... .... @b3_rd_rs_imm5
550+# SHLL rs, rd
551+SHLL_rr 1111 1101 0110 0010 .... .... @b3_rd_rs
552+
553+# SHLR #imm, rd
554+SHLR_irr 0110 100. .... .... @b2_rds_imm5
555+# SHLR #imm, rs, rd
556+SHLR_irr 1111 1101 100. .... .... .... @b3_rd_rs_imm5
557+# SHLR rs, rd
558+SHLR_rr 1111 1101 0110 0000 .... .... @b3_rd_rs
559+
560+# SMOVB
561+# SSTR.<bwl>
562+{
563+ SMOVB 0111 1111 1000 1011
564+ SSTR 0111 1111 1000 10 sz:2
565+}
566+
567+# STNZ #imm, rd
568+STNZ 1111 1101 0111 ..00 1111 .... @b3_rd_li
569+# STZ #imm, rd
570+STZ 1111 1101 0111 ..00 1110 .... @b3_rd_li
571+
572+# SUB #uimm4, rd
573+SUB_ir 0110 0000 .... .... @b2_rds_uimm4
574+# SUB dsp[rs].ub, rd
575+# SUB rs, rd
576+SUB_mr 0100 00.. .... .... @b2_rd_ld_ub
577+# SUB dsp[rs], rd
578+SUB_mr 0000 0110 ..00 00.. .... .... @b3_rd_ld
579+# SUB rs, rs2, rd
580+SUB_rrr 1111 1111 0000 .... .... .... @b3_rd_rs_rs2
581+
582+# SCMPU
583+# SUNTIL.<bwl>
584+{
585+ SCMPU 0111 1111 1000 0011
586+ SUNTIL 0111 1111 1000 00 sz:2
587+}
588+
589+# SMOVU
590+# SWHILE.<bwl>
591+{
592+ SMOVU 0111 1111 1000 0111
593+ SWHILE 0111 1111 1000 01 sz:2
594+}
595+
596+# TST #imm, rd
597+TST_ir 1111 1101 0111 ..00 1100 .... @b3_rd_li
598+# TST dsp[rs].ub, rd
599+# TST rs, rd
600+TST_mr 1111 1100 0011 00.. .... .... @b3_rd_ld_ub
601+# TST dsp[rs], rd
602+TST_mr 0000 0110 ..10 00.. 0000 1100 .... .... @b4_rd_ldmi
603+
604+WAIT 0111 1111 1001 0110
605+
606+# XCHG rs, rd
607+# XCHG dsp[rs].ub, rd
608+{
609+ XCHG_rr 1111 1100 0100 0011 .... .... @b3_rd_rs
610+ XCHG_mr 1111 1100 0100 00.. .... .... @b3_rd_ld_ub
611+}
612+# XCHG dsp[rs], rd
613+XCHG_mr 0000 0110 ..10 00.. 0001 0000 .... .... @b4_rd_ldmi
614+
615+# XOR #imm, rd
616+XOR_ir 1111 1101 0111 ..00 1101 .... @b3_rd_li
617+# XOR dsp[rs].ub, rd
618+# XOR rs, rd
619+XOR_mr 1111 1100 0011 01.. .... .... @b3_rd_ld_ub
620+# XOR dsp[rs], rd
621+XOR_mr 0000 0110 ..10 00.. 0000 1101 .... .... @b4_rd_ldmi
--- /dev/null
+++ b/target/rx/translate.c
@@ -0,0 +1,2432 @@
1+/*
2+ * RX translation
3+ *
4+ * Copyright (c) 2019 Yoshinori Sato
5+ *
6+ * This program is free software; you can redistribute it and/or modify it
7+ * under the terms and conditions of the GNU General Public License,
8+ * version 2 or later, as published by the Free Software Foundation.
9+ *
10+ * This program is distributed in the hope it will be useful, but WITHOUT
11+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13+ * more details.
14+ *
15+ * You should have received a copy of the GNU General Public License along with
16+ * this program. If not, see <http://www.gnu.org/licenses/>.
17+ */
18+
19+#include "qemu/osdep.h"
20+#include "qemu/bswap.h"
21+#include "qemu/qemu-print.h"
22+#include "cpu.h"
23+#include "exec/exec-all.h"
24+#include "tcg-op.h"
25+#include "exec/cpu_ldst.h"
26+#include "exec/helper-proto.h"
27+#include "exec/helper-gen.h"
28+#include "exec/translator.h"
29+#include "trace-tcg.h"
30+#include "exec/log.h"
31+
32+typedef struct DisasContext {
33+ DisasContextBase base;
34+ CPURXState *env;
35+ uint32_t pc;
36+} DisasContext;
37+
38+typedef struct DisasCompare {
39+ TCGv value;
40+ TCGv temp;
41+ TCGCond cond;
42+} DisasCompare;
43+
44+const char rx_crname[][6] = {
45+ "psw", "pc", "usp", "fpsw", "", "", "", "",
46+ "bpsw", "bpc", "isp", "fintv", "intb", "", "", "",
47+};
48+
49+/* Target-specific values for dc->base.is_jmp. */
50+#define DISAS_JUMP DISAS_TARGET_0
51+#define DISAS_UPDATE DISAS_TARGET_1
52+#define DISAS_EXIT DISAS_TARGET_2
53+
54+/* global register indexes */
55+static TCGv cpu_regs[16];
56+static TCGv cpu_psw_o, cpu_psw_s, cpu_psw_z, cpu_psw_c;
57+static TCGv cpu_psw_i, cpu_psw_pm, cpu_psw_u, cpu_psw_ipl;
58+static TCGv cpu_usp, cpu_fpsw, cpu_bpsw, cpu_bpc, cpu_isp;
59+static TCGv cpu_fintv, cpu_intb, cpu_pc;
60+static TCGv_i64 cpu_acc;
61+
62+#define cpu_sp cpu_regs[0]
63+
64+#include "exec/gen-icount.h"
65+
66+/* decoder helper */
67+static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
68+ int i, int n)
69+{
70+ while (++i <= n) {
71+ uint8_t b = cpu_ldub_code(ctx->env, ctx->base.pc_next++);
72+ insn |= b << (32 - i * 8);
73+ }
74+ return insn;
75+}
76+
77+static uint32_t li(DisasContext *ctx, int sz)
78+{
79+ int32_t tmp, addr;
80+ CPURXState *env = ctx->env;
81+ addr = ctx->base.pc_next;
82+
83+ tcg_debug_assert(sz < 4);
84+ switch (sz) {
85+ case 1:
86+ ctx->base.pc_next += 1;
87+ return cpu_ldsb_code(env, addr);
88+ case 2:
89+ ctx->base.pc_next += 2;
90+ return cpu_ldsw_code(env, addr);
91+ case 3:
92+ ctx->base.pc_next += 3;
93+ tmp = cpu_ldsb_code(env, addr + 2) << 16;
94+ tmp |= cpu_lduw_code(env, addr) & 0xffff;
95+ return tmp;
96+ case 0:
97+ ctx->base.pc_next += 4;
98+ return cpu_ldl_code(env, addr);
99+ }
100+ return 0;
101+}
102+
103+static int bdsp_s(DisasContext *ctx, int d)
104+{
105+ /*
106+ * 0 -> 8
107+ * 1 -> 9
108+ * 2 -> 10
109+ * 3 -> 3
110+ * :
111+ * 7 -> 7
112+ */
113+ if (d < 3) {
114+ d += 8;
115+ }
116+ return d;
117+}
118+
119+/* Include the auto-generated decoder. */
120+#include "decode.inc.c"
121+
122+void rx_cpu_dump_state(CPUState *cs, FILE *f, int flags)
123+{
124+ RXCPU *cpu = RXCPU(cs);
125+ CPURXState *env = &cpu->env;
126+ int i;
127+ uint32_t psw;
128+
129+ psw = rx_cpu_pack_psw(env);
130+ qemu_fprintf(f, "pc=0x%08x psw=0x%08x\n",
131+ env->pc, psw);
132+ for (i = 0; i < 16; i += 4) {
133+ qemu_fprintf(f, "r%d=0x%08x r%d=0x%08x r%d=0x%08x r%d=0x%08x\n",
134+ i, env->regs[i], i + 1, env->regs[i + 1],
135+ i + 2, env->regs[i + 2], i + 3, env->regs[i + 3]);
136+ }
137+}
138+
139+static bool use_goto_tb(DisasContext *dc, target_ulong dest)
140+{
141+ if (unlikely(dc->base.singlestep_enabled)) {
142+ return false;
143+ } else {
144+ return true;
145+ }
146+}
147+
148+static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
149+{
150+ if (use_goto_tb(dc, dest)) {
151+ tcg_gen_goto_tb(n);
152+ tcg_gen_movi_i32(cpu_pc, dest);
153+ tcg_gen_exit_tb(dc->base.tb, n);
154+ } else {
155+ tcg_gen_movi_i32(cpu_pc, dest);
156+ if (dc->base.singlestep_enabled) {
157+ gen_helper_debug(cpu_env);
158+ } else {
159+ tcg_gen_lookup_and_goto_ptr();
160+ }
161+ }
162+ dc->base.is_jmp = DISAS_NORETURN;
163+}
164+
165+/* generic load wrapper */
166+static inline void rx_gen_ld(unsigned int size, TCGv reg, TCGv mem)
167+{
168+ tcg_gen_qemu_ld_i32(reg, mem, 0, size | MO_SIGN | MO_TE);
169+}
170+
171+/* unsigned load wrapper */
172+static inline void rx_gen_ldu(unsigned int size, TCGv reg, TCGv mem)
173+{
174+ tcg_gen_qemu_ld_i32(reg, mem, 0, size | MO_TE);
175+}
176+
177+/* generic store wrapper */
178+static inline void rx_gen_st(unsigned int size, TCGv reg, TCGv mem)
179+{
180+ tcg_gen_qemu_st_i32(reg, mem, 0, size | MO_TE);
181+}
182+
183+/* [ri, rb] */
184+static inline void rx_gen_regindex(DisasContext *ctx, TCGv mem,
185+ int size, int ri, int rb)
186+{
187+ tcg_gen_shli_i32(mem, cpu_regs[ri], size);
188+ tcg_gen_add_i32(mem, mem, cpu_regs[rb]);
189+}
190+
191+/* dsp[reg] */
192+static inline TCGv rx_index_addr(DisasContext *ctx, TCGv mem,
193+ int ld, int size, int reg)
194+{
195+ uint32_t dsp;
196+
197+ tcg_debug_assert(ld < 3);
198+ switch (ld) {
199+ case 0:
200+ return cpu_regs[reg];
201+ case 1:
202+ dsp = cpu_ldub_code(ctx->env, ctx->base.pc_next) << size;
203+ tcg_gen_addi_i32(mem, cpu_regs[reg], dsp);
204+ ctx->base.pc_next += 1;
205+ return mem;
206+ case 2:
207+ dsp = cpu_lduw_code(ctx->env, ctx->base.pc_next) << size;
208+ tcg_gen_addi_i32(mem, cpu_regs[reg], dsp);
209+ ctx->base.pc_next += 2;
210+ return mem;
211+ }
212+ return NULL;
213+}
214+
215+static inline MemOp mi_to_mop(unsigned mi)
216+{
217+ static const MemOp mop[5] = { MO_SB, MO_SW, MO_UL, MO_UW, MO_UB };
218+ tcg_debug_assert(mi < 5);
219+ return mop[mi];
220+}
221+
222+/* load source operand */
223+static inline TCGv rx_load_source(DisasContext *ctx, TCGv mem,
224+ int ld, int mi, int rs)
225+{
226+ TCGv addr;
227+ MemOp mop;
228+ if (ld < 3) {
229+ mop = mi_to_mop(mi);
230+ addr = rx_index_addr(ctx, mem, ld, mop & MO_SIZE, rs);
231+ tcg_gen_qemu_ld_i32(mem, addr, 0, mop | MO_TE);
232+ return mem;
233+ } else {
234+ return cpu_regs[rs];
235+ }
236+}
237+
238+/* Processor mode check */
239+static int is_privileged(DisasContext *ctx, int is_exception)
240+{
241+ if (FIELD_EX32(ctx->base.tb->flags, PSW, PM)) {
242+ if (is_exception) {
243+ gen_helper_raise_privilege_violation(cpu_env);
244+ }
245+ return 0;
246+ } else {
247+ return 1;
248+ }
249+}
250+
251+/* generate QEMU condition */
252+static void psw_cond(DisasCompare *dc, uint32_t cond)
253+{
254+ tcg_debug_assert(cond < 16);
255+ switch (cond) {
256+ case 0: /* z */
257+ dc->cond = TCG_COND_EQ;
258+ dc->value = cpu_psw_z;
259+ break;
260+ case 1: /* nz */
261+ dc->cond = TCG_COND_NE;
262+ dc->value = cpu_psw_z;
263+ break;
264+ case 2: /* c */
265+ dc->cond = TCG_COND_NE;
266+ dc->value = cpu_psw_c;
267+ break;
268+ case 3: /* nc */
269+ dc->cond = TCG_COND_EQ;
270+ dc->value = cpu_psw_c;
271+ break;
272+ case 4: /* gtu (C& ~Z) == 1 */
273+ case 5: /* leu (C& ~Z) == 0 */
274+ tcg_gen_setcondi_i32(TCG_COND_NE, dc->temp, cpu_psw_z, 0);
275+ tcg_gen_and_i32(dc->temp, dc->temp, cpu_psw_c);
276+ dc->cond = (cond == 4) ? TCG_COND_NE : TCG_COND_EQ;
277+ dc->value = dc->temp;
278+ break;
279+ case 6: /* pz (S == 0) */
280+ dc->cond = TCG_COND_GE;
281+ dc->value = cpu_psw_s;
282+ break;
283+ case 7: /* n (S == 1) */
284+ dc->cond = TCG_COND_LT;
285+ dc->value = cpu_psw_s;
286+ break;
287+ case 8: /* ge (S^O)==0 */
288+ case 9: /* lt (S^O)==1 */
289+ tcg_gen_xor_i32(dc->temp, cpu_psw_o, cpu_psw_s);
290+ dc->cond = (cond == 8) ? TCG_COND_GE : TCG_COND_LT;
291+ dc->value = dc->temp;
292+ break;
293+ case 10: /* gt ((S^O)|Z)==0 */
294+ case 11: /* le ((S^O)|Z)==1 */
295+ tcg_gen_xor_i32(dc->temp, cpu_psw_o, cpu_psw_s);
296+ tcg_gen_sari_i32(dc->temp, dc->temp, 31);
297+ tcg_gen_andc_i32(dc->temp, cpu_psw_z, dc->temp);
298+ dc->cond = (cond == 10) ? TCG_COND_NE : TCG_COND_EQ;
299+ dc->value = dc->temp;
300+ break;
301+ case 12: /* o */
302+ dc->cond = TCG_COND_LT;
303+ dc->value = cpu_psw_o;
304+ break;
305+ case 13: /* no */
306+ dc->cond = TCG_COND_GE;
307+ dc->value = cpu_psw_o;
308+ break;
309+ case 14: /* always true */
310+ dc->cond = TCG_COND_ALWAYS;
311+ dc->value = dc->temp;
312+ break;
313+ case 15: /* always false */
314+ dc->cond = TCG_COND_NEVER;
315+ dc->value = dc->temp;
316+ break;
317+ }
318+}
319+
320+static void move_from_cr(TCGv ret, int cr, uint32_t pc)
321+{
322+ TCGv z = tcg_const_i32(0);
323+ switch (cr) {
324+ case 0: /* PSW */
325+ gen_helper_pack_psw(ret, cpu_env);
326+ break;
327+ case 1: /* PC */
328+ tcg_gen_movi_i32(ret, pc);
329+ break;
330+ case 2: /* USP */
331+ tcg_gen_movcond_i32(TCG_COND_NE, ret,
332+ cpu_psw_u, z, cpu_sp, cpu_usp);
333+ break;
334+ case 3: /* FPSW */
335+ tcg_gen_mov_i32(ret, cpu_fpsw);
336+ break;
337+ case 8: /* BPSW */
338+ tcg_gen_mov_i32(ret, cpu_bpsw);
339+ break;
340+ case 9: /* BPC */
341+ tcg_gen_mov_i32(ret, cpu_bpc);
342+ break;
343+ case 10: /* ISP */
344+ tcg_gen_movcond_i32(TCG_COND_EQ, ret,
345+ cpu_psw_u, z, cpu_sp, cpu_isp);
346+ break;
347+ case 11: /* FINTV */
348+ tcg_gen_mov_i32(ret, cpu_fintv);
349+ break;
350+ case 12: /* INTB */
351+ tcg_gen_mov_i32(ret, cpu_intb);
352+ break;
353+ default:
354+ qemu_log_mask(LOG_GUEST_ERROR, "Unimplement control register %d", cr);
355+ /* Unimplement registers return 0 */
356+ tcg_gen_movi_i32(ret, 0);
357+ break;
358+ }
359+ tcg_temp_free(z);
360+}
361+
362+static void move_to_cr(DisasContext *ctx, TCGv val, int cr)
363+{
364+ TCGv z;
365+ if (cr >= 8 && !is_privileged(ctx, 0)) {
366+ /* Some control registers can only be written in privileged mode. */
367+ qemu_log_mask(LOG_GUEST_ERROR,
368+ "disallow control register write %s", rx_crname[cr]);
369+ return;
370+ }
371+ z = tcg_const_i32(0);
372+ switch (cr) {
373+ case 0: /* PSW */
374+ gen_helper_set_psw(cpu_env, val);
375+ break;
376+ /* case 1: to PC not supported */
377+ case 2: /* USP */
378+ tcg_gen_mov_i32(cpu_usp, val);
379+ tcg_gen_movcond_i32(TCG_COND_NE, cpu_sp,
380+ cpu_psw_u, z, cpu_usp, cpu_sp);
381+ break;
382+ case 3: /* FPSW */
383+ gen_helper_set_fpsw(cpu_env, val);
384+ break;
385+ case 8: /* BPSW */
386+ tcg_gen_mov_i32(cpu_bpsw, val);
387+ break;
388+ case 9: /* BPC */
389+ tcg_gen_mov_i32(cpu_bpc, val);
390+ break;
391+ case 10: /* ISP */
392+ tcg_gen_mov_i32(cpu_isp, val);
393+ /* if PSW.U is 0, copy isp to r0 */
394+ tcg_gen_movcond_i32(TCG_COND_EQ, cpu_sp,
395+ cpu_psw_u, z, cpu_isp, cpu_sp);
396+ break;
397+ case 11: /* FINTV */
398+ tcg_gen_mov_i32(cpu_fintv, val);
399+ break;
400+ case 12: /* INTB */
401+ tcg_gen_mov_i32(cpu_intb, val);
402+ break;
403+ default:
404+ qemu_log_mask(LOG_GUEST_ERROR,
405+ "Unimplement control register %d", cr);
406+ break;
407+ }
408+ tcg_temp_free(z);
409+}
410+
411+static void push(TCGv val)
412+{
413+ tcg_gen_subi_i32(cpu_sp, cpu_sp, 4);
414+ rx_gen_st(MO_32, val, cpu_sp);
415+}
416+
417+static void pop(TCGv ret)
418+{
419+ rx_gen_ld(MO_32, ret, cpu_sp);
420+ tcg_gen_addi_i32(cpu_sp, cpu_sp, 4);
421+}
422+
423+/* mov.<bwl> rs,dsp5[rd] */
424+static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a)
425+{
426+ TCGv mem;
427+ mem = tcg_temp_new();
428+ tcg_gen_addi_i32(mem, cpu_regs[a->rd], a->dsp << a->sz);
429+ rx_gen_st(a->sz, cpu_regs[a->rs], mem);
430+ tcg_temp_free(mem);
431+ return true;
432+}
433+
434+/* mov.<bwl> dsp5[rs],rd */
435+static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a)
436+{
437+ TCGv mem;
438+ mem = tcg_temp_new();
439+ tcg_gen_addi_i32(mem, cpu_regs[a->rs], a->dsp << a->sz);
440+ rx_gen_ld(a->sz, cpu_regs[a->rd], mem);
441+ tcg_temp_free(mem);
442+ return true;
443+}
444+
445+/* mov.l #uimm4,rd */
446+/* mov.l #uimm8,rd */
447+/* mov.l #imm,rd */
448+static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a)
449+{
450+ tcg_gen_movi_i32(cpu_regs[a->rd], a->imm);
451+ return true;
452+}
453+
454+/* mov.<bwl> #uimm8,dsp[rd] */
455+/* mov.<bwl> #imm, dsp[rd] */
456+static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a)
457+{
458+ TCGv imm, mem;
459+ imm = tcg_const_i32(a->imm);
460+ mem = tcg_temp_new();
461+ tcg_gen_addi_i32(mem, cpu_regs[a->rd], a->dsp << a->sz);
462+ rx_gen_st(a->sz, imm, mem);
463+ tcg_temp_free(imm);
464+ tcg_temp_free(mem);
465+ return true;
466+}
467+
468+/* mov.<bwl> [ri,rb],rd */
469+static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a)
470+{
471+ TCGv mem;
472+ mem = tcg_temp_new();
473+ rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb);
474+ rx_gen_ld(a->sz, cpu_regs[a->rd], mem);
475+ tcg_temp_free(mem);
476+ return true;
477+}
478+
479+/* mov.<bwl> rd,[ri,rb] */
480+static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a)
481+{
482+ TCGv mem;
483+ mem = tcg_temp_new();
484+ rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb);
485+ rx_gen_st(a->sz, cpu_regs[a->rs], mem);
486+ tcg_temp_free(mem);
487+ return true;
488+}
489+
490+/* mov.<bwl> dsp[rs],dsp[rd] */
491+/* mov.<bwl> rs,dsp[rd] */
492+/* mov.<bwl> dsp[rs],rd */
493+/* mov.<bwl> rs,rd */
494+static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a)
495+{
496+ static void (* const mov[])(TCGv ret, TCGv arg) = {
497+ tcg_gen_ext8s_i32, tcg_gen_ext16s_i32, tcg_gen_mov_i32,
498+ };
499+ TCGv tmp, mem, addr;
500+ if (a->lds == 3 && a->ldd == 3) {
501+ /* mov.<bwl> rs,rd */
502+ mov[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
503+ return true;
504+ }
505+
506+ mem = tcg_temp_new();
507+ if (a->lds == 3) {
508+ /* mov.<bwl> rs,dsp[rd] */
509+ addr = rx_index_addr(ctx, mem, a->ldd, a->sz, a->rs);
510+ rx_gen_st(a->sz, cpu_regs[a->rd], addr);
511+ } else if (a->ldd == 3) {
512+ /* mov.<bwl> dsp[rs],rd */
513+ addr = rx_index_addr(ctx, mem, a->lds, a->sz, a->rs);
514+ rx_gen_ld(a->sz, cpu_regs[a->rd], addr);
515+ } else {
516+ /* mov.<bwl> dsp[rs],dsp[rd] */
517+ tmp = tcg_temp_new();
518+ addr = rx_index_addr(ctx, mem, a->lds, a->sz, a->rs);
519+ rx_gen_ld(a->sz, tmp, addr);
520+ addr = rx_index_addr(ctx, mem, a->ldd, a->sz, a->rd);
521+ rx_gen_st(a->sz, tmp, addr);
522+ tcg_temp_free(tmp);
523+ }
524+ tcg_temp_free(mem);
525+ return true;
526+}
527+
528+/* mov.<bwl> rs,[rd+] */
529+/* mov.<bwl> rs,[-rd] */
530+static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a)
531+{
532+ TCGv val;
533+ val = tcg_temp_new();
534+ tcg_gen_mov_i32(val, cpu_regs[a->rs]);
535+ if (a->ad == 1) {
536+ tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
537+ }
538+ rx_gen_st(a->sz, val, cpu_regs[a->rd]);
539+ if (a->ad == 0) {
540+ tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
541+ }
542+ tcg_temp_free(val);
543+ return true;
544+}
545+
546+/* mov.<bwl> [rd+],rs */
547+/* mov.<bwl> [-rd],rs */
548+static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a)
549+{
550+ TCGv val;
551+ val = tcg_temp_new();
552+ if (a->ad == 1) {
553+ tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
554+ }
555+ rx_gen_ld(a->sz, val, cpu_regs[a->rd]);
556+ if (a->ad == 0) {
557+ tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
558+ }
559+ tcg_gen_mov_i32(cpu_regs[a->rs], val);
560+ tcg_temp_free(val);
561+ return true;
562+}
563+
564+/* movu.<bw> dsp5[rs],rd */
565+/* movu.<bw> dsp[rs],rd */
566+static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a)
567+{
568+ TCGv mem;
569+ mem = tcg_temp_new();
570+ tcg_gen_addi_i32(mem, cpu_regs[a->rs], a->dsp << a->sz);
571+ rx_gen_ldu(a->sz, cpu_regs[a->rd], mem);
572+ tcg_temp_free(mem);
573+ return true;
574+}
575+
576+/* movu.<bw> rs,rd */
577+static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a)
578+{
579+ static void (* const ext[])(TCGv ret, TCGv arg) = {
580+ tcg_gen_ext8u_i32, tcg_gen_ext16u_i32,
581+ };
582+ ext[a->sz](cpu_regs[a->rd], cpu_regs[a->rs]);
583+ return true;
584+}
585+
586+/* movu.<bw> [ri,rb],rd */
587+static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a)
588+{
589+ TCGv mem;
590+ mem = tcg_temp_new();
591+ rx_gen_regindex(ctx, mem, a->sz, a->ri, a->rb);
592+ rx_gen_ldu(a->sz, cpu_regs[a->rd], mem);
593+ tcg_temp_free(mem);
594+ return true;
595+}
596+
597+/* movu.<bw> [rd+],rs */
598+/* mov.<bw> [-rd],rs */
599+static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a)
600+{
601+ TCGv val;
602+ val = tcg_temp_new();
603+ if (a->ad == 1) {
604+ tcg_gen_subi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
605+ }
606+ rx_gen_ldu(a->sz, val, cpu_regs[a->rd]);
607+ if (a->ad == 0) {
608+ tcg_gen_addi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1 << a->sz);
609+ }
610+ tcg_gen_mov_i32(cpu_regs[a->rs], val);
611+ tcg_temp_free(val);
612+ return true;
613+}
614+
615+
616+/* pop rd */
617+static bool trans_POP(DisasContext *ctx, arg_POP *a)
618+{
619+ /* mov.l [r0+], rd */
620+ arg_MOV_rp mov_a;
621+ mov_a.rd = 0;
622+ mov_a.rs = a->rd;
623+ mov_a.ad = 0;
624+ mov_a.sz = MO_32;
625+ trans_MOV_pr(ctx, &mov_a);
626+ return true;
627+}
628+
629+/* popc cr */
630+static bool trans_POPC(DisasContext *ctx, arg_POPC *a)
631+{
632+ TCGv val;
633+ val = tcg_temp_new();
634+ pop(val);
635+ move_to_cr(ctx, val, a->cr);
636+ if (a->cr == 0 && is_privileged(ctx, 0)) {
637+ /* PSW.I may be updated here. exit TB. */
638+ ctx->base.is_jmp = DISAS_UPDATE;
639+ }
640+ tcg_temp_free(val);
641+ return true;
642+}
643+
644+/* popm rd-rd2 */
645+static bool trans_POPM(DisasContext *ctx, arg_POPM *a)
646+{
647+ int r;
648+ if (a->rd == 0 || a->rd >= a->rd2) {
649+ qemu_log_mask(LOG_GUEST_ERROR,
650+ "Invalid register ranges r%d-r%d", a->rd, a->rd2);
651+ }
652+ r = a->rd;
653+ while (r <= a->rd2 && r < 16) {
654+ pop(cpu_regs[r++]);
655+ }
656+ return true;
657+}
658+
659+
660+/* push.<bwl> rs */
661+static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a)
662+{
663+ TCGv val;
664+ val = tcg_temp_new();
665+ tcg_gen_mov_i32(val, cpu_regs[a->rs]);
666+ tcg_gen_subi_i32(cpu_sp, cpu_sp, 4);
667+ rx_gen_st(a->sz, val, cpu_sp);
668+ tcg_temp_free(val);
669+ return true;
670+}
671+
672+/* push.<bwl> dsp[rs] */
673+static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a)
674+{
675+ TCGv mem, val, addr;
676+ mem = tcg_temp_new();
677+ val = tcg_temp_new();
678+ addr = rx_index_addr(ctx, mem, a->ld, a->sz, a->rs);
679+ rx_gen_ld(a->sz, val, addr);
680+ tcg_gen_subi_i32(cpu_sp, cpu_sp, 4);
681+ rx_gen_st(a->sz, val, cpu_sp);
682+ tcg_temp_free(mem);
683+ tcg_temp_free(val);
684+ return true;
685+}
686+
687+/* pushc rx */
688+static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a)
689+{
690+ TCGv val;
691+ val = tcg_temp_new();
692+ move_from_cr(val, a->cr, ctx->pc);
693+ push(val);
694+ tcg_temp_free(val);
695+ return true;
696+}
697+
698+/* pushm rs-rs2 */
699+static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a)
700+{
701+ int r;
702+
703+ if (a->rs == 0 || a->rs >= a->rs2) {
704+ qemu_log_mask(LOG_GUEST_ERROR,
705+ "Invalid register ranges r%d-r%d", a->rs, a->rs2);
706+ }
707+ r = a->rs2;
708+ while (r >= a->rs && r >= 0) {
709+ push(cpu_regs[r--]);
710+ }
711+ return true;
712+}
713+
714+/* xchg rs,rd */
715+static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a)
716+{
717+ TCGv tmp;
718+ tmp = tcg_temp_new();
719+ tcg_gen_mov_i32(tmp, cpu_regs[a->rs]);
720+ tcg_gen_mov_i32(cpu_regs[a->rs], cpu_regs[a->rd]);
721+ tcg_gen_mov_i32(cpu_regs[a->rd], tmp);
722+ tcg_temp_free(tmp);
723+ return true;
724+}
725+
726+/* xchg dsp[rs].<mi>,rd */
727+static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a)
728+{
729+ TCGv mem, addr;
730+ mem = tcg_temp_new();
731+ switch (a->mi) {
732+ case 0: /* dsp[rs].b */
733+ case 1: /* dsp[rs].w */
734+ case 2: /* dsp[rs].l */
735+ addr = rx_index_addr(ctx, mem, a->ld, a->mi, a->rs);
736+ break;
737+ case 3: /* dsp[rs].uw */
738+ case 4: /* dsp[rs].ub */
739+ addr = rx_index_addr(ctx, mem, a->ld, 4 - a->mi, a->rs);
740+ break;
741+ default:
742+ g_assert_not_reached();
743+ }
744+ tcg_gen_atomic_xchg_i32(cpu_regs[a->rd], addr, cpu_regs[a->rd],
745+ 0, mi_to_mop(a->mi));
746+ tcg_temp_free(mem);
747+ return true;
748+}
749+
750+static inline void stcond(TCGCond cond, int rd, int imm)
751+{
752+ TCGv z;
753+ TCGv _imm;
754+ z = tcg_const_i32(0);
755+ _imm = tcg_const_i32(imm);
756+ tcg_gen_movcond_i32(cond, cpu_regs[rd], cpu_psw_z, z,
757+ _imm, cpu_regs[rd]);
758+ tcg_temp_free(z);
759+ tcg_temp_free(_imm);
760+}
761+
762+/* stz #imm,rd */
763+static bool trans_STZ(DisasContext *ctx, arg_STZ *a)
764+{
765+ stcond(TCG_COND_EQ, a->rd, a->imm);
766+ return true;
767+}
768+
769+/* stnz #imm,rd */
770+static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a)
771+{
772+ stcond(TCG_COND_NE, a->rd, a->imm);
773+ return true;
774+}
775+
776+/* sccnd.<bwl> rd */
777+/* sccnd.<bwl> dsp:[rd] */
778+static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a)
779+{
780+ DisasCompare dc;
781+ TCGv val, mem, addr;
782+ dc.temp = tcg_temp_new();
783+ psw_cond(&dc, a->cd);
784+ if (a->ld < 3) {
785+ val = tcg_temp_new();
786+ mem = tcg_temp_new();
787+ tcg_gen_setcondi_i32(dc.cond, val, dc.value, 0);
788+ addr = rx_index_addr(ctx, mem, a->sz, a->ld, a->rd);
789+ rx_gen_st(a->sz, val, addr);
790+ tcg_temp_free(val);
791+ tcg_temp_free(mem);
792+ } else {
793+ tcg_gen_setcondi_i32(dc.cond, cpu_regs[a->rd], dc.value, 0);
794+ }
795+ tcg_temp_free(dc.temp);
796+ return true;
797+}
798+
799+/* rtsd #imm */
800+static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a)
801+{
802+ tcg_gen_addi_i32(cpu_sp, cpu_sp, a->imm << 2);
803+ pop(cpu_pc);
804+ ctx->base.is_jmp = DISAS_JUMP;
805+ return true;
806+}
807+
808+/* rtsd #imm, rd-rd2 */
809+static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a)
810+{
811+ int dst;
812+ int adj;
813+
814+ if (a->rd2 >= a->rd) {
815+ adj = a->imm - (a->rd2 - a->rd + 1);
816+ } else {
817+ adj = a->imm - (15 - a->rd + 1);
818+ }
819+
820+ tcg_gen_addi_i32(cpu_sp, cpu_sp, adj << 2);
821+ dst = a->rd;
822+ while (dst <= a->rd2 && dst < 16) {
823+ pop(cpu_regs[dst++]);
824+ }
825+ pop(cpu_pc);
826+ ctx->base.is_jmp = DISAS_JUMP;
827+ return true;
828+}
829+
830+typedef void (*op2fn)(TCGv ret, TCGv arg1);
831+typedef void (*op3fn)(TCGv ret, TCGv arg1, TCGv arg2);
832+
833+static inline void rx_gen_op_rr(op2fn opr, int dst, int src)
834+{
835+ opr(cpu_regs[dst], cpu_regs[src]);
836+}
837+
838+static inline void rx_gen_op_rrr(op3fn opr, int dst, int src, int src2)
839+{
840+ opr(cpu_regs[dst], cpu_regs[src], cpu_regs[src2]);
841+}
842+
843+static inline void rx_gen_op_irr(op3fn opr, int dst, int src, uint32_t src2)
844+{
845+ TCGv imm = tcg_const_i32(src2);
846+ opr(cpu_regs[dst], cpu_regs[src], imm);
847+ tcg_temp_free(imm);
848+}
849+
850+static inline void rx_gen_op_mr(op3fn opr, DisasContext *ctx,
851+ int dst, int src, int ld, int mi)
852+{
853+ TCGv val, mem;
854+ mem = tcg_temp_new();
855+ val = rx_load_source(ctx, mem, ld, mi, src);
856+ opr(cpu_regs[dst], cpu_regs[dst], val);
857+ tcg_temp_free(mem);
858+}
859+
860+static void rx_and(TCGv ret, TCGv arg1, TCGv arg2)
861+{
862+ tcg_gen_and_i32(cpu_psw_s, arg1, arg2);
863+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
864+ tcg_gen_mov_i32(ret, cpu_psw_s);
865+}
866+
867+/* and #uimm:4, rd */
868+/* and #imm, rd */
869+static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a)
870+{
871+ rx_gen_op_irr(rx_and, a->rd, a->rd, a->imm);
872+ return true;
873+}
874+
875+/* and dsp[rs], rd */
876+/* and rs,rd */
877+static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a)
878+{
879+ rx_gen_op_mr(rx_and, ctx, a->rd, a->rs, a->ld, a->mi);
880+ return true;
881+}
882+
883+/* and rs,rs2,rd */
884+static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a)
885+{
886+ rx_gen_op_rrr(rx_and, a->rd, a->rs, a->rs2);
887+ return true;
888+}
889+
890+static void rx_or(TCGv ret, TCGv arg1, TCGv arg2)
891+{
892+ tcg_gen_or_i32(cpu_psw_s, arg1, arg2);
893+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
894+ tcg_gen_mov_i32(ret, cpu_psw_s);
895+}
896+
897+/* or #uimm:4, rd */
898+/* or #imm, rd */
899+static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a)
900+{
901+ rx_gen_op_irr(rx_or, a->rd, a->rd, a->imm);
902+ return true;
903+}
904+
905+/* or dsp[rs], rd */
906+/* or rs,rd */
907+static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a)
908+{
909+ rx_gen_op_mr(rx_or, ctx, a->rd, a->rs, a->ld, a->mi);
910+ return true;
911+}
912+
913+/* or rs,rs2,rd */
914+static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a)
915+{
916+ rx_gen_op_rrr(rx_or, a->rd, a->rs, a->rs2);
917+ return true;
918+}
919+
920+static void rx_xor(TCGv ret, TCGv arg1, TCGv arg2)
921+{
922+ tcg_gen_xor_i32(cpu_psw_s, arg1, arg2);
923+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
924+ tcg_gen_mov_i32(ret, cpu_psw_s);
925+}
926+
927+/* xor #imm, rd */
928+static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a)
929+{
930+ rx_gen_op_irr(rx_xor, a->rd, a->rd, a->imm);
931+ return true;
932+}
933+
934+/* xor dsp[rs], rd */
935+/* xor rs,rd */
936+static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a)
937+{
938+ rx_gen_op_mr(rx_xor, ctx, a->rd, a->rs, a->ld, a->mi);
939+ return true;
940+}
941+
942+static void rx_tst(TCGv ret, TCGv arg1, TCGv arg2)
943+{
944+ tcg_gen_and_i32(cpu_psw_s, arg1, arg2);
945+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
946+}
947+
948+/* tst #imm, rd */
949+static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a)
950+{
951+ rx_gen_op_irr(rx_tst, a->rd, a->rd, a->imm);
952+ return true;
953+}
954+
955+/* tst dsp[rs], rd */
956+/* tst rs, rd */
957+static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a)
958+{
959+ rx_gen_op_mr(rx_tst, ctx, a->rd, a->rs, a->ld, a->mi);
960+ return true;
961+}
962+
963+static void rx_not(TCGv ret, TCGv arg1)
964+{
965+ tcg_gen_not_i32(ret, arg1);
966+ tcg_gen_mov_i32(cpu_psw_z, ret);
967+ tcg_gen_mov_i32(cpu_psw_s, ret);
968+}
969+
970+/* not rd */
971+/* not rs, rd */
972+static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a)
973+{
974+ rx_gen_op_rr(rx_not, a->rd, a->rs);
975+ return true;
976+}
977+
978+static void rx_neg(TCGv ret, TCGv arg1)
979+{
980+ tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, arg1, 0x80000000);
981+ tcg_gen_neg_i32(ret, arg1);
982+ tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_c, ret, 0);
983+ tcg_gen_mov_i32(cpu_psw_z, ret);
984+ tcg_gen_mov_i32(cpu_psw_s, ret);
985+}
986+
987+
988+/* neg rd */
989+/* neg rs, rd */
990+static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a)
991+{
992+ rx_gen_op_rr(rx_neg, a->rd, a->rs);
993+ return true;
994+}
995+
996+/* ret = arg1 + arg2 + psw_c */
997+static void rx_adc(TCGv ret, TCGv arg1, TCGv arg2)
998+{
999+ TCGv z;
1000+ z = tcg_const_i32(0);
1001+ tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, arg1, z, cpu_psw_c, z);
1002+ tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, cpu_psw_s, cpu_psw_c, arg2, z);
1003+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
1004+ tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1);
1005+ tcg_gen_xor_i32(z, arg1, arg2);
1006+ tcg_gen_andc_i32(cpu_psw_o, cpu_psw_o, z);
1007+ tcg_gen_mov_i32(ret, cpu_psw_s);
1008+ tcg_temp_free(z);
1009+}
1010+
1011+/* adc #imm, rd */
1012+static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a)
1013+{
1014+ rx_gen_op_irr(rx_adc, a->rd, a->rd, a->imm);
1015+ return true;
1016+}
1017+
1018+/* adc rs, rd */
1019+static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a)
1020+{
1021+ rx_gen_op_rrr(rx_adc, a->rd, a->rd, a->rs);
1022+ return true;
1023+}
1024+
1025+/* adc dsp[rs], rd */
1026+static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a)
1027+{
1028+ /* mi only 2 */
1029+ if (a->mi != 2) {
1030+ return false;
1031+ }
1032+ rx_gen_op_mr(rx_adc, ctx, a->rd, a->rs, a->ld, a->mi);
1033+ return true;
1034+}
1035+
1036+/* ret = arg1 + arg2 */
1037+static void rx_add(TCGv ret, TCGv arg1, TCGv arg2)
1038+{
1039+ TCGv z;
1040+ z = tcg_const_i32(0);
1041+ tcg_gen_add2_i32(cpu_psw_s, cpu_psw_c, arg1, z, arg2, z);
1042+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
1043+ tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1);
1044+ tcg_gen_xor_i32(z, arg1, arg2);
1045+ tcg_gen_andc_i32(cpu_psw_o, cpu_psw_o, z);
1046+ tcg_gen_mov_i32(ret, cpu_psw_s);
1047+ tcg_temp_free(z);
1048+}
1049+
1050+/* add #uimm4, rd */
1051+/* add #imm, rs, rd */
1052+static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a)
1053+{
1054+ rx_gen_op_irr(rx_add, a->rd, a->rs2, a->imm);
1055+ return true;
1056+}
1057+
1058+/* add rs, rd */
1059+/* add dsp[rs], rd */
1060+static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a)
1061+{
1062+ rx_gen_op_mr(rx_add, ctx, a->rd, a->rs, a->ld, a->mi);
1063+ return true;
1064+}
1065+
1066+/* add rs, rs2, rd */
1067+static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a)
1068+{
1069+ rx_gen_op_rrr(rx_add, a->rd, a->rs, a->rs2);
1070+ return true;
1071+}
1072+
1073+/* ret = arg1 - arg2 */
1074+static void rx_sub(TCGv ret, TCGv arg1, TCGv arg2)
1075+{
1076+ TCGv temp;
1077+ tcg_gen_sub_i32(cpu_psw_s, arg1, arg2);
1078+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_s);
1079+ tcg_gen_setcond_i32(TCG_COND_GEU, cpu_psw_c, arg1, arg2);
1080+ tcg_gen_xor_i32(cpu_psw_o, cpu_psw_s, arg1);
1081+ temp = tcg_temp_new_i32();
1082+ tcg_gen_xor_i32(temp, arg1, arg2);
1083+ tcg_gen_and_i32(cpu_psw_o, cpu_psw_o, temp);
1084+ tcg_temp_free_i32(temp);
1085+ /* CMP not requred return */
1086+ if (ret) {
1087+ tcg_gen_mov_i32(ret, cpu_psw_s);
1088+ }
1089+}
1090+static void rx_cmp(TCGv dummy, TCGv arg1, TCGv arg2)
1091+{
1092+ rx_sub(NULL, arg1, arg2);
1093+}
1094+/* ret = arg1 - arg2 - !psw_c */
1095+/* -> ret = arg1 + ~arg2 + psw_c */
1096+static void rx_sbb(TCGv ret, TCGv arg1, TCGv arg2)
1097+{
1098+ TCGv temp;
1099+ temp = tcg_temp_new();
1100+ tcg_gen_not_i32(temp, arg2);
1101+ rx_adc(ret, arg1, temp);
1102+ tcg_temp_free(temp);
1103+}
1104+
1105+/* cmp #imm4, rs2 */
1106+/* cmp #imm8, rs2 */
1107+/* cmp #imm, rs2 */
1108+static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a)
1109+{
1110+ rx_gen_op_irr(rx_cmp, 0, a->rs2, a->imm);
1111+ return true;
1112+}
1113+
1114+/* cmp rs, rs2 */
1115+/* cmp dsp[rs], rs2 */
1116+static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a)
1117+{
1118+ rx_gen_op_mr(rx_cmp, ctx, a->rd, a->rs, a->ld, a->mi);
1119+ return true;
1120+}
1121+
1122+/* sub #imm4, rd */
1123+static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a)
1124+{
1125+ rx_gen_op_irr(rx_sub, a->rd, a->rd, a->imm);
1126+ return true;
1127+}
1128+
1129+/* sub rs, rd */
1130+/* sub dsp[rs], rd */
1131+static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a)
1132+{
1133+ rx_gen_op_mr(rx_sub, ctx, a->rd, a->rs, a->ld, a->mi);
1134+ return true;
1135+}
1136+
1137+/* sub rs2, rs, rd */
1138+static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a)
1139+{
1140+ rx_gen_op_rrr(rx_sub, a->rd, a->rs2, a->rs);
1141+ return true;
1142+}
1143+
1144+/* sbb rs, rd */
1145+static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a)
1146+{
1147+ rx_gen_op_rrr(rx_sbb, a->rd, a->rd, a->rs);
1148+ return true;
1149+}
1150+
1151+/* sbb dsp[rs], rd */
1152+static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a)
1153+{
1154+ /* mi only 2 */
1155+ if (a->mi != 2) {
1156+ return false;
1157+ }
1158+ rx_gen_op_mr(rx_sbb, ctx, a->rd, a->rs, a->ld, a->mi);
1159+ return true;
1160+}
1161+
1162+static void rx_abs(TCGv ret, TCGv arg1)
1163+{
1164+ TCGv neg;
1165+ TCGv zero;
1166+ neg = tcg_temp_new();
1167+ zero = tcg_const_i32(0);
1168+ tcg_gen_neg_i32(neg, arg1);
1169+ tcg_gen_movcond_i32(TCG_COND_LT, ret, arg1, zero, neg, arg1);
1170+ tcg_temp_free(neg);
1171+ tcg_temp_free(zero);
1172+}
1173+
1174+/* abs rd */
1175+/* abs rs, rd */
1176+static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a)
1177+{
1178+ rx_gen_op_rr(rx_abs, a->rd, a->rs);
1179+ return true;
1180+}
1181+
1182+/* max #imm, rd */
1183+static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a)
1184+{
1185+ rx_gen_op_irr(tcg_gen_smax_i32, a->rd, a->rd, a->imm);
1186+ return true;
1187+}
1188+
1189+/* max rs, rd */
1190+/* max dsp[rs], rd */
1191+static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a)
1192+{
1193+ rx_gen_op_mr(tcg_gen_smax_i32, ctx, a->rd, a->rs, a->ld, a->mi);
1194+ return true;
1195+}
1196+
1197+/* min #imm, rd */
1198+static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a)
1199+{
1200+ rx_gen_op_irr(tcg_gen_smin_i32, a->rd, a->rd, a->imm);
1201+ return true;
1202+}
1203+
1204+/* min rs, rd */
1205+/* min dsp[rs], rd */
1206+static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a)
1207+{
1208+ rx_gen_op_mr(tcg_gen_smin_i32, ctx, a->rd, a->rs, a->ld, a->mi);
1209+ return true;
1210+}
1211+
1212+/* mul #uimm4, rd */
1213+/* mul #imm, rd */
1214+static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a)
1215+{
1216+ rx_gen_op_irr(tcg_gen_mul_i32, a->rd, a->rd, a->imm);
1217+ return true;
1218+}
1219+
1220+/* mul rs, rd */
1221+/* mul dsp[rs], rd */
1222+static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a)
1223+{
1224+ rx_gen_op_mr(tcg_gen_mul_i32, ctx, a->rd, a->rs, a->ld, a->mi);
1225+ return true;
1226+}
1227+
1228+/* mul rs, rs2, rd */
1229+static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a)
1230+{
1231+ rx_gen_op_rrr(tcg_gen_mul_i32, a->rd, a->rs, a->rs2);
1232+ return true;
1233+}
1234+
1235+/* emul #imm, rd */
1236+static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a)
1237+{
1238+ TCGv imm = tcg_const_i32(a->imm);
1239+ if (a->rd > 14) {
1240+ qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1241+ }
1242+ tcg_gen_muls2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1243+ cpu_regs[a->rd], imm);
1244+ tcg_temp_free(imm);
1245+ return true;
1246+}
1247+
1248+/* emul rs, rd */
1249+/* emul dsp[rs], rd */
1250+static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a)
1251+{
1252+ TCGv val, mem;
1253+ if (a->rd > 14) {
1254+ qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1255+ }
1256+ mem = tcg_temp_new();
1257+ val = rx_load_source(ctx, mem, a->ld, a->mi, a->rs);
1258+ tcg_gen_muls2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1259+ cpu_regs[a->rd], val);
1260+ tcg_temp_free(mem);
1261+ return true;
1262+}
1263+
1264+/* emulu #imm, rd */
1265+static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a)
1266+{
1267+ TCGv imm = tcg_const_i32(a->imm);
1268+ if (a->rd > 14) {
1269+ qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1270+ }
1271+ tcg_gen_mulu2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1272+ cpu_regs[a->rd], imm);
1273+ tcg_temp_free(imm);
1274+ return true;
1275+}
1276+
1277+/* emulu rs, rd */
1278+/* emulu dsp[rs], rd */
1279+static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a)
1280+{
1281+ TCGv val, mem;
1282+ if (a->rd > 14) {
1283+ qemu_log_mask(LOG_GUEST_ERROR, "rd too large %d", a->rd);
1284+ }
1285+ mem = tcg_temp_new();
1286+ val = rx_load_source(ctx, mem, a->ld, a->mi, a->rs);
1287+ tcg_gen_mulu2_i32(cpu_regs[a->rd], cpu_regs[(a->rd + 1) & 15],
1288+ cpu_regs[a->rd], val);
1289+ tcg_temp_free(mem);
1290+ return true;
1291+}
1292+
1293+static void rx_div(TCGv ret, TCGv arg1, TCGv arg2)
1294+{
1295+ gen_helper_div(ret, cpu_env, arg1, arg2);
1296+}
1297+
1298+static void rx_divu(TCGv ret, TCGv arg1, TCGv arg2)
1299+{
1300+ gen_helper_divu(ret, cpu_env, arg1, arg2);
1301+}
1302+
1303+/* div #imm, rd */
1304+static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a)
1305+{
1306+ rx_gen_op_irr(rx_div, a->rd, a->rd, a->imm);
1307+ return true;
1308+}
1309+
1310+/* div rs, rd */
1311+/* div dsp[rs], rd */
1312+static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a)
1313+{
1314+ rx_gen_op_mr(rx_div, ctx, a->rd, a->rs, a->ld, a->mi);
1315+ return true;
1316+}
1317+
1318+/* divu #imm, rd */
1319+static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a)
1320+{
1321+ rx_gen_op_irr(rx_divu, a->rd, a->rd, a->imm);
1322+ return true;
1323+}
1324+
1325+/* divu rs, rd */
1326+/* divu dsp[rs], rd */
1327+static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a)
1328+{
1329+ rx_gen_op_mr(rx_divu, ctx, a->rd, a->rs, a->ld, a->mi);
1330+ return true;
1331+}
1332+
1333+
1334+/* shll #imm:5, rd */
1335+/* shll #imm:5, rs2, rd */
1336+static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a)
1337+{
1338+ TCGv tmp;
1339+ tmp = tcg_temp_new();
1340+ if (a->imm) {
1341+ tcg_gen_sari_i32(cpu_psw_c, cpu_regs[a->rs2], 32 - a->imm);
1342+ tcg_gen_shli_i32(cpu_regs[a->rd], cpu_regs[a->rs2], a->imm);
1343+ tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, cpu_psw_c, 0);
1344+ tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_psw_c, 0xffffffff);
1345+ tcg_gen_or_i32(cpu_psw_o, cpu_psw_o, tmp);
1346+ tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, cpu_psw_c, 0);
1347+ } else {
1348+ tcg_gen_mov_i32(cpu_regs[a->rd], cpu_regs[a->rs2]);
1349+ tcg_gen_movi_i32(cpu_psw_c, 0);
1350+ tcg_gen_movi_i32(cpu_psw_o, 0);
1351+ }
1352+ tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1353+ tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1354+ return true;
1355+}
1356+
1357+/* shll rs, rd */
1358+static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a)
1359+{
1360+ TCGLabel *noshift, *done;
1361+ TCGv count, tmp;
1362+
1363+ noshift = gen_new_label();
1364+ done = gen_new_label();
1365+ /* if (cpu_regs[a->rs]) { */
1366+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_regs[a->rs], 0, noshift);
1367+ count = tcg_const_i32(32);
1368+ tmp = tcg_temp_new();
1369+ tcg_gen_andi_i32(tmp, cpu_regs[a->rs], 31);
1370+ tcg_gen_sub_i32(count, count, tmp);
1371+ tcg_gen_sar_i32(cpu_psw_c, cpu_regs[a->rd], count);
1372+ tcg_gen_shl_i32(cpu_regs[a->rd], cpu_regs[a->rd], tmp);
1373+ tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_psw_o, cpu_psw_c, 0);
1374+ tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_psw_c, 0xffffffff);
1375+ tcg_gen_or_i32(cpu_psw_o, cpu_psw_o, tmp);
1376+ tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, cpu_psw_c, 0);
1377+ tcg_gen_br(done);
1378+ /* } else { */
1379+ gen_set_label(noshift);
1380+ tcg_gen_movi_i32(cpu_psw_c, 0);
1381+ tcg_gen_movi_i32(cpu_psw_o, 0);
1382+ /* } */
1383+ gen_set_label(done);
1384+ tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1385+ tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1386+ tcg_temp_free(count);
1387+ tcg_temp_free(tmp);
1388+ return true;
1389+}
1390+
1391+static inline void shiftr_imm(uint32_t rd, uint32_t rs, uint32_t imm,
1392+ unsigned int alith)
1393+{
1394+ static void (* const gen_sXri[])(TCGv ret, TCGv arg1, int arg2) = {
1395+ tcg_gen_shri_i32, tcg_gen_sari_i32,
1396+ };
1397+ tcg_debug_assert(alith < 2);
1398+ if (imm) {
1399+ gen_sXri[alith](cpu_regs[rd], cpu_regs[rs], imm - 1);
1400+ tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001);
1401+ gen_sXri[alith](cpu_regs[rd], cpu_regs[rd], 1);
1402+ } else {
1403+ tcg_gen_mov_i32(cpu_regs[rd], cpu_regs[rs]);
1404+ tcg_gen_movi_i32(cpu_psw_c, 0);
1405+ }
1406+ tcg_gen_movi_i32(cpu_psw_o, 0);
1407+ tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]);
1408+ tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]);
1409+}
1410+
1411+static inline void shiftr_reg(uint32_t rd, uint32_t rs, unsigned int alith)
1412+{
1413+ TCGLabel *noshift, *done;
1414+ TCGv count;
1415+ static void (* const gen_sXri[])(TCGv ret, TCGv arg1, int arg2) = {
1416+ tcg_gen_shri_i32, tcg_gen_sari_i32,
1417+ };
1418+ static void (* const gen_sXr[])(TCGv ret, TCGv arg1, TCGv arg2) = {
1419+ tcg_gen_shr_i32, tcg_gen_sar_i32,
1420+ };
1421+ tcg_debug_assert(alith < 2);
1422+ noshift = gen_new_label();
1423+ done = gen_new_label();
1424+ count = tcg_temp_new();
1425+ /* if (cpu_regs[rs]) { */
1426+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_regs[rs], 0, noshift);
1427+ tcg_gen_andi_i32(count, cpu_regs[rs], 31);
1428+ tcg_gen_subi_i32(count, count, 1);
1429+ gen_sXr[alith](cpu_regs[rd], cpu_regs[rd], count);
1430+ tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001);
1431+ gen_sXri[alith](cpu_regs[rd], cpu_regs[rd], 1);
1432+ tcg_gen_br(done);
1433+ /* } else { */
1434+ gen_set_label(noshift);
1435+ tcg_gen_movi_i32(cpu_psw_c, 0);
1436+ /* } */
1437+ gen_set_label(done);
1438+ tcg_gen_movi_i32(cpu_psw_o, 0);
1439+ tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]);
1440+ tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]);
1441+ tcg_temp_free(count);
1442+}
1443+
1444+/* shar #imm:5, rd */
1445+/* shar #imm:5, rs2, rd */
1446+static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a)
1447+{
1448+ shiftr_imm(a->rd, a->rs2, a->imm, 1);
1449+ return true;
1450+}
1451+
1452+/* shar rs, rd */
1453+static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a)
1454+{
1455+ shiftr_reg(a->rd, a->rs, 1);
1456+ return true;
1457+}
1458+
1459+/* shlr #imm:5, rd */
1460+/* shlr #imm:5, rs2, rd */
1461+static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a)
1462+{
1463+ shiftr_imm(a->rd, a->rs2, a->imm, 0);
1464+ return true;
1465+}
1466+
1467+/* shlr rs, rd */
1468+static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a)
1469+{
1470+ shiftr_reg(a->rd, a->rs, 0);
1471+ return true;
1472+}
1473+
1474+/* rolc rd */
1475+static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a)
1476+{
1477+ TCGv tmp;
1478+ tmp = tcg_temp_new();
1479+ tcg_gen_shri_i32(tmp, cpu_regs[a->rd], 31);
1480+ tcg_gen_shli_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1);
1481+ tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], cpu_psw_c);
1482+ tcg_gen_mov_i32(cpu_psw_c, tmp);
1483+ tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1484+ tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1485+ tcg_temp_free(tmp);
1486+ return true;
1487+}
1488+
1489+/* rorc rd */
1490+static bool trans_RORC(DisasContext *ctx, arg_RORC *a)
1491+{
1492+ TCGv tmp;
1493+ tmp = tcg_temp_new();
1494+ tcg_gen_andi_i32(tmp, cpu_regs[a->rd], 0x00000001);
1495+ tcg_gen_shri_i32(cpu_regs[a->rd], cpu_regs[a->rd], 1);
1496+ tcg_gen_shli_i32(cpu_psw_c, cpu_psw_c, 31);
1497+ tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], cpu_psw_c);
1498+ tcg_gen_mov_i32(cpu_psw_c, tmp);
1499+ tcg_gen_mov_i32(cpu_psw_z, cpu_regs[a->rd]);
1500+ tcg_gen_mov_i32(cpu_psw_s, cpu_regs[a->rd]);
1501+ return true;
1502+}
1503+
1504+enum {ROTR = 0, ROTL = 1};
1505+enum {ROT_IMM = 0, ROT_REG = 1};
1506+static inline void rx_rot(int ir, int dir, int rd, int src)
1507+{
1508+ switch (dir) {
1509+ case ROTL:
1510+ if (ir == ROT_IMM) {
1511+ tcg_gen_rotli_i32(cpu_regs[rd], cpu_regs[rd], src);
1512+ } else {
1513+ tcg_gen_rotl_i32(cpu_regs[rd], cpu_regs[rd], cpu_regs[src]);
1514+ }
1515+ tcg_gen_andi_i32(cpu_psw_c, cpu_regs[rd], 0x00000001);
1516+ break;
1517+ case ROTR:
1518+ if (ir == ROT_IMM) {
1519+ tcg_gen_rotri_i32(cpu_regs[rd], cpu_regs[rd], src);
1520+ } else {
1521+ tcg_gen_rotr_i32(cpu_regs[rd], cpu_regs[rd], cpu_regs[src]);
1522+ }
1523+ tcg_gen_shri_i32(cpu_psw_c, cpu_regs[rd], 31);
1524+ break;
1525+ }
1526+ tcg_gen_mov_i32(cpu_psw_z, cpu_regs[rd]);
1527+ tcg_gen_mov_i32(cpu_psw_s, cpu_regs[rd]);
1528+}
1529+
1530+/* rotl #imm, rd */
1531+static bool trans_ROTL_ir(DisasContext *ctx, arg_ROTL_ir *a)
1532+{
1533+ rx_rot(ROT_IMM, ROTL, a->rd, a->imm);
1534+ return true;
1535+}
1536+
1537+/* rotl rs, rd */
1538+static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a)
1539+{
1540+ rx_rot(ROT_REG, ROTL, a->rd, a->rs);
1541+ return true;
1542+}
1543+
1544+/* rotr #imm, rd */
1545+static bool trans_ROTR_ir(DisasContext *ctx, arg_ROTR_ir *a)
1546+{
1547+ rx_rot(ROT_IMM, ROTR, a->rd, a->imm);
1548+ return true;
1549+}
1550+
1551+/* rotr rs, rd */
1552+static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a)
1553+{
1554+ rx_rot(ROT_REG, ROTR, a->rd, a->rs);
1555+ return true;
1556+}
1557+
1558+/* revl rs, rd */
1559+static bool trans_REVL(DisasContext *ctx, arg_REVL *a)
1560+{
1561+ tcg_gen_bswap32_i32(cpu_regs[a->rd], cpu_regs[a->rs]);
1562+ return true;
1563+}
1564+
1565+/* revw rs, rd */
1566+static bool trans_REVW(DisasContext *ctx, arg_REVW *a)
1567+{
1568+ TCGv tmp;
1569+ tmp = tcg_temp_new();
1570+ tcg_gen_andi_i32(tmp, cpu_regs[a->rs], 0x00ff00ff);
1571+ tcg_gen_shli_i32(tmp, tmp, 8);
1572+ tcg_gen_shri_i32(cpu_regs[a->rd], cpu_regs[a->rs], 8);
1573+ tcg_gen_andi_i32(cpu_regs[a->rd], cpu_regs[a->rd], 0x00ff00ff);
1574+ tcg_gen_or_i32(cpu_regs[a->rd], cpu_regs[a->rd], tmp);
1575+ tcg_temp_free(tmp);
1576+ return true;
1577+}
1578+
1579+/* conditional branch helper */
1580+static void rx_bcnd_main(DisasContext *ctx, int cd, int dst)
1581+{
1582+ DisasCompare dc;
1583+ TCGLabel *t, *done;
1584+
1585+ switch (cd) {
1586+ case 0 ... 13:
1587+ dc.temp = tcg_temp_new();
1588+ psw_cond(&dc, cd);
1589+ t = gen_new_label();
1590+ done = gen_new_label();
1591+ tcg_gen_brcondi_i32(dc.cond, dc.value, 0, t);
1592+ gen_goto_tb(ctx, 0, ctx->base.pc_next);
1593+ tcg_gen_br(done);
1594+ gen_set_label(t);
1595+ gen_goto_tb(ctx, 1, ctx->pc + dst);
1596+ gen_set_label(done);
1597+ tcg_temp_free(dc.temp);
1598+ break;
1599+ case 14:
1600+ /* always true case */
1601+ gen_goto_tb(ctx, 0, ctx->pc + dst);
1602+ break;
1603+ case 15:
1604+ /* always false case */
1605+ /* Nothing do */
1606+ break;
1607+ }
1608+}
1609+
1610+/* beq dsp:3 / bne dsp:3 */
1611+/* beq dsp:8 / bne dsp:8 */
1612+/* bc dsp:8 / bnc dsp:8 */
1613+/* bgtu dsp:8 / bleu dsp:8 */
1614+/* bpz dsp:8 / bn dsp:8 */
1615+/* bge dsp:8 / blt dsp:8 */
1616+/* bgt dsp:8 / ble dsp:8 */
1617+/* bo dsp:8 / bno dsp:8 */
1618+/* beq dsp:16 / bne dsp:16 */
1619+static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a)
1620+{
1621+ rx_bcnd_main(ctx, a->cd, a->dsp);
1622+ return true;
1623+}
1624+
1625+/* bra dsp:3 */
1626+/* bra dsp:8 */
1627+/* bra dsp:16 */
1628+/* bra dsp:24 */
1629+static bool trans_BRA(DisasContext *ctx, arg_BRA *a)
1630+{
1631+ rx_bcnd_main(ctx, 14, a->dsp);
1632+ return true;
1633+}
1634+
1635+/* bra rs */
1636+static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a)
1637+{
1638+ tcg_gen_addi_i32(cpu_pc, cpu_regs[a->rd], ctx->pc);
1639+ ctx->base.is_jmp = DISAS_JUMP;
1640+ return true;
1641+}
1642+
1643+static inline void rx_save_pc(DisasContext *ctx)
1644+{
1645+ TCGv pc = tcg_const_i32(ctx->base.pc_next);
1646+ push(pc);
1647+ tcg_temp_free(pc);
1648+}
1649+
1650+/* jmp rs */
1651+static bool trans_JMP(DisasContext *ctx, arg_JMP *a)
1652+{
1653+ tcg_gen_mov_i32(cpu_pc, cpu_regs[a->rs]);
1654+ ctx->base.is_jmp = DISAS_JUMP;
1655+ return true;
1656+}
1657+
1658+/* jsr rs */
1659+static bool trans_JSR(DisasContext *ctx, arg_JSR *a)
1660+{
1661+ rx_save_pc(ctx);
1662+ tcg_gen_mov_i32(cpu_pc, cpu_regs[a->rs]);
1663+ ctx->base.is_jmp = DISAS_JUMP;
1664+ return true;
1665+}
1666+
1667+/* bsr dsp:16 */
1668+/* bsr dsp:24 */
1669+static bool trans_BSR(DisasContext *ctx, arg_BSR *a)
1670+{
1671+ rx_save_pc(ctx);
1672+ rx_bcnd_main(ctx, 14, a->dsp);
1673+ return true;
1674+}
1675+
1676+/* bsr rs */
1677+static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a)
1678+{
1679+ rx_save_pc(ctx);
1680+ tcg_gen_addi_i32(cpu_pc, cpu_regs[a->rd], ctx->pc);
1681+ ctx->base.is_jmp = DISAS_JUMP;
1682+ return true;
1683+}
1684+
1685+/* rts */
1686+static bool trans_RTS(DisasContext *ctx, arg_RTS *a)
1687+{
1688+ pop(cpu_pc);
1689+ ctx->base.is_jmp = DISAS_JUMP;
1690+ return true;
1691+}
1692+
1693+/* nop */
1694+static bool trans_NOP(DisasContext *ctx, arg_NOP *a)
1695+{
1696+ return true;
1697+}
1698+
1699+/* scmpu */
1700+static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a)
1701+{
1702+ gen_helper_scmpu(cpu_env);
1703+ return true;
1704+}
1705+
1706+/* smovu */
1707+static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a)
1708+{
1709+ gen_helper_smovu(cpu_env);
1710+ return true;
1711+}
1712+
1713+/* smovf */
1714+static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a)
1715+{
1716+ gen_helper_smovf(cpu_env);
1717+ return true;
1718+}
1719+
1720+/* smovb */
1721+static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a)
1722+{
1723+ gen_helper_smovb(cpu_env);
1724+ return true;
1725+}
1726+
1727+#define STRING(op) \
1728+ do { \
1729+ TCGv size = tcg_const_i32(a->sz); \
1730+ gen_helper_##op(cpu_env, size); \
1731+ tcg_temp_free(size); \
1732+ } while (0)
1733+
1734+/* suntile.<bwl> */
1735+static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a)
1736+{
1737+ STRING(suntil);
1738+ return true;
1739+}
1740+
1741+/* swhile.<bwl> */
1742+static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a)
1743+{
1744+ STRING(swhile);
1745+ return true;
1746+}
1747+/* sstr.<bwl> */
1748+static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a)
1749+{
1750+ STRING(sstr);
1751+ return true;
1752+}
1753+
1754+/* rmpa.<bwl> */
1755+static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a)
1756+{
1757+ STRING(rmpa);
1758+ return true;
1759+}
1760+
1761+static void rx_mul64hi(TCGv_i64 ret, int rs, int rs2)
1762+{
1763+ TCGv_i64 tmp0, tmp1;
1764+ tmp0 = tcg_temp_new_i64();
1765+ tmp1 = tcg_temp_new_i64();
1766+ tcg_gen_ext_i32_i64(tmp0, cpu_regs[rs]);
1767+ tcg_gen_sari_i64(tmp0, tmp0, 16);
1768+ tcg_gen_ext_i32_i64(tmp1, cpu_regs[rs2]);
1769+ tcg_gen_sari_i64(tmp1, tmp1, 16);
1770+ tcg_gen_mul_i64(ret, tmp0, tmp1);
1771+ tcg_gen_shli_i64(ret, ret, 16);
1772+ tcg_temp_free_i64(tmp0);
1773+ tcg_temp_free_i64(tmp1);
1774+}
1775+
1776+static void rx_mul64lo(TCGv_i64 ret, int rs, int rs2)
1777+{
1778+ TCGv_i64 tmp0, tmp1;
1779+ tmp0 = tcg_temp_new_i64();
1780+ tmp1 = tcg_temp_new_i64();
1781+ tcg_gen_ext_i32_i64(tmp0, cpu_regs[rs]);
1782+ tcg_gen_ext16s_i64(tmp0, tmp0);
1783+ tcg_gen_ext_i32_i64(tmp1, cpu_regs[rs2]);
1784+ tcg_gen_ext16s_i64(tmp1, tmp1);
1785+ tcg_gen_mul_i64(ret, tmp0, tmp1);
1786+ tcg_gen_shli_i64(ret, ret, 16);
1787+ tcg_temp_free_i64(tmp0);
1788+ tcg_temp_free_i64(tmp1);
1789+}
1790+
1791+/* mulhi rs,rs2 */
1792+static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a)
1793+{
1794+ rx_mul64hi(cpu_acc, a->rs, a->rs2);
1795+ return true;
1796+}
1797+
1798+/* mullo rs,rs2 */
1799+static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a)
1800+{
1801+ rx_mul64lo(cpu_acc, a->rs, a->rs2);
1802+ return true;
1803+}
1804+
1805+/* machi rs,rs2 */
1806+static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a)
1807+{
1808+ TCGv_i64 tmp;
1809+ tmp = tcg_temp_new_i64();
1810+ rx_mul64hi(tmp, a->rs, a->rs2);
1811+ tcg_gen_add_i64(cpu_acc, cpu_acc, tmp);
1812+ tcg_temp_free_i64(tmp);
1813+ return true;
1814+}
1815+
1816+/* maclo rs,rs2 */
1817+static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a)
1818+{
1819+ TCGv_i64 tmp;
1820+ tmp = tcg_temp_new_i64();
1821+ rx_mul64lo(tmp, a->rs, a->rs2);
1822+ tcg_gen_add_i64(cpu_acc, cpu_acc, tmp);
1823+ tcg_temp_free_i64(tmp);
1824+ return true;
1825+}
1826+
1827+/* mvfachi rd */
1828+static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a)
1829+{
1830+ tcg_gen_extrh_i64_i32(cpu_regs[a->rd], cpu_acc);
1831+ return true;
1832+}
1833+
1834+/* mvfacmi rd */
1835+static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a)
1836+{
1837+ TCGv_i64 rd64;
1838+ rd64 = tcg_temp_new_i64();
1839+ tcg_gen_extract_i64(rd64, cpu_acc, 16, 32);
1840+ tcg_gen_extrl_i64_i32(cpu_regs[a->rd], rd64);
1841+ tcg_temp_free_i64(rd64);
1842+ return true;
1843+}
1844+
1845+/* mvtachi rs */
1846+static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a)
1847+{
1848+ TCGv_i64 rs64;
1849+ rs64 = tcg_temp_new_i64();
1850+ tcg_gen_extu_i32_i64(rs64, cpu_regs[a->rs]);
1851+ tcg_gen_deposit_i64(cpu_acc, cpu_acc, rs64, 32, 32);
1852+ tcg_temp_free_i64(rs64);
1853+ return true;
1854+}
1855+
1856+/* mvtaclo rs */
1857+static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a)
1858+{
1859+ TCGv_i64 rs64;
1860+ rs64 = tcg_temp_new_i64();
1861+ tcg_gen_extu_i32_i64(rs64, cpu_regs[a->rs]);
1862+ tcg_gen_deposit_i64(cpu_acc, cpu_acc, rs64, 0, 32);
1863+ tcg_temp_free_i64(rs64);
1864+ return true;
1865+}
1866+
1867+/* racw #imm */
1868+static bool trans_RACW(DisasContext *ctx, arg_RACW *a)
1869+{
1870+ TCGv imm = tcg_const_i32(a->imm + 1);
1871+ gen_helper_racw(cpu_env, imm);
1872+ tcg_temp_free(imm);
1873+ return true;
1874+}
1875+
1876+/* sat rd */
1877+static bool trans_SAT(DisasContext *ctx, arg_SAT *a)
1878+{
1879+ TCGv tmp, z;
1880+ tmp = tcg_temp_new();
1881+ z = tcg_const_i32(0);
1882+ /* S == 1 -> 0xffffffff / S == 0 -> 0x00000000 */
1883+ tcg_gen_sari_i32(tmp, cpu_psw_s, 31);
1884+ /* S == 1 -> 0x7fffffff / S == 0 -> 0x80000000 */
1885+ tcg_gen_xori_i32(tmp, tmp, 0x80000000);
1886+ tcg_gen_movcond_i32(TCG_COND_LT, cpu_regs[a->rd],
1887+ cpu_psw_o, z, tmp, cpu_regs[a->rd]);
1888+ tcg_temp_free(tmp);
1889+ tcg_temp_free(z);
1890+ return true;
1891+}
1892+
1893+/* satr */
1894+static bool trans_SATR(DisasContext *ctx, arg_SATR *a)
1895+{
1896+ gen_helper_satr(cpu_env);
1897+ return true;
1898+}
1899+
1900+#define cat3(a, b, c) a##b##c
1901+#define FOP(name, op) \
1902+ static bool cat3(trans_, name, _ir)(DisasContext *ctx, \
1903+ cat3(arg_, name, _ir) * a) \
1904+ { \
1905+ TCGv imm = tcg_const_i32(li(ctx, 0)); \
1906+ gen_helper_##op(cpu_regs[a->rd], cpu_env, \
1907+ cpu_regs[a->rd], imm); \
1908+ tcg_temp_free(imm); \
1909+ return true; \
1910+ } \
1911+ static bool cat3(trans_, name, _mr)(DisasContext *ctx, \
1912+ cat3(arg_, name, _mr) * a) \
1913+ { \
1914+ TCGv val, mem; \
1915+ mem = tcg_temp_new(); \
1916+ val = rx_load_source(ctx, mem, a->ld, MO_32, a->rs); \
1917+ gen_helper_##op(cpu_regs[a->rd], cpu_env, \
1918+ cpu_regs[a->rd], val); \
1919+ tcg_temp_free(mem); \
1920+ return true; \
1921+ }
1922+
1923+#define FCONVOP(name, op) \
1924+ static bool trans_##name(DisasContext *ctx, arg_##name * a) \
1925+ { \
1926+ TCGv val, mem; \
1927+ mem = tcg_temp_new(); \
1928+ val = rx_load_source(ctx, mem, a->ld, MO_32, a->rs); \
1929+ gen_helper_##op(cpu_regs[a->rd], cpu_env, val); \
1930+ tcg_temp_free(mem); \
1931+ return true; \
1932+ }
1933+
1934+FOP(FADD, fadd)
1935+FOP(FSUB, fsub)
1936+FOP(FMUL, fmul)
1937+FOP(FDIV, fdiv)
1938+
1939+/* fcmp #imm, rd */
1940+static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir * a)
1941+{
1942+ TCGv imm = tcg_const_i32(li(ctx, 0));
1943+ gen_helper_fcmp(cpu_env, cpu_regs[a->rd], imm);
1944+ tcg_temp_free(imm);
1945+ return true;
1946+}
1947+
1948+/* fcmp dsp[rs], rd */
1949+/* fcmp rs, rd */
1950+static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a)
1951+{
1952+ TCGv val, mem;
1953+ mem = tcg_temp_new();
1954+ val = rx_load_source(ctx, mem, a->ld, MO_32, a->rs);
1955+ gen_helper_fcmp(cpu_env, cpu_regs[a->rd], val);
1956+ tcg_temp_free(mem);
1957+ return true;
1958+}
1959+
1960+FCONVOP(FTOI, ftoi)
1961+FCONVOP(ROUND, round)
1962+
1963+/* itof rs, rd */
1964+/* itof dsp[rs], rd */
1965+static bool trans_ITOF(DisasContext *ctx, arg_ITOF * a)
1966+{
1967+ TCGv val, mem;
1968+ mem = tcg_temp_new();
1969+ val = rx_load_source(ctx, mem, a->ld, a->mi, a->rs);
1970+ gen_helper_itof(cpu_regs[a->rd], cpu_env, val);
1971+ tcg_temp_free(mem);
1972+ return true;
1973+}
1974+
1975+static void rx_bsetm(TCGv mem, TCGv mask)
1976+{
1977+ TCGv val;
1978+ val = tcg_temp_new();
1979+ rx_gen_ld(MO_8, val, mem);
1980+ tcg_gen_or_i32(val, val, mask);
1981+ rx_gen_st(MO_8, val, mem);
1982+ tcg_temp_free(val);
1983+}
1984+
1985+static void rx_bclrm(TCGv mem, TCGv mask)
1986+{
1987+ TCGv val;
1988+ val = tcg_temp_new();
1989+ rx_gen_ld(MO_8, val, mem);
1990+ tcg_gen_andc_i32(val, val, mask);
1991+ rx_gen_st(MO_8, val, mem);
1992+ tcg_temp_free(val);
1993+}
1994+
1995+static void rx_btstm(TCGv mem, TCGv mask)
1996+{
1997+ TCGv val;
1998+ val = tcg_temp_new();
1999+ rx_gen_ld(MO_8, val, mem);
2000+ tcg_gen_and_i32(val, val, mask);
2001+ tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, val, 0);
2002+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_c);
2003+ tcg_temp_free(val);
2004+}
2005+
2006+static void rx_bnotm(TCGv mem, TCGv mask)
2007+{
2008+ TCGv val;
2009+ val = tcg_temp_new();
2010+ rx_gen_ld(MO_8, val, mem);
2011+ tcg_gen_xor_i32(val, val, mask);
2012+ rx_gen_st(MO_8, val, mem);
2013+ tcg_temp_free(val);
2014+}
2015+
2016+static void rx_bsetr(TCGv reg, TCGv mask)
2017+{
2018+ tcg_gen_or_i32(reg, reg, mask);
2019+}
2020+
2021+static void rx_bclrr(TCGv reg, TCGv mask)
2022+{
2023+ tcg_gen_andc_i32(reg, reg, mask);
2024+}
2025+
2026+static inline void rx_btstr(TCGv reg, TCGv mask)
2027+{
2028+ TCGv t0;
2029+ t0 = tcg_temp_new();
2030+ tcg_gen_and_i32(t0, reg, mask);
2031+ tcg_gen_setcondi_i32(TCG_COND_NE, cpu_psw_c, t0, 0);
2032+ tcg_gen_mov_i32(cpu_psw_z, cpu_psw_c);
2033+ tcg_temp_free(t0);
2034+}
2035+
2036+static inline void rx_bnotr(TCGv reg, TCGv mask)
2037+{
2038+ tcg_gen_xor_i32(reg, reg, mask);
2039+}
2040+
2041+#define BITOP(name, op) \
2042+ static bool cat3(trans_, name, _im)(DisasContext *ctx, \
2043+ cat3(arg_, name, _im) * a) \
2044+ { \
2045+ TCGv mask, mem, addr; \
2046+ mem = tcg_temp_new(); \
2047+ mask = tcg_const_i32(1 << a->imm); \
2048+ addr = rx_index_addr(ctx, mem, a->ld, MO_8, a->rs); \
2049+ cat3(rx_, op, m)(addr, mask); \
2050+ tcg_temp_free(mask); \
2051+ tcg_temp_free(mem); \
2052+ return true; \
2053+ } \
2054+ static bool cat3(trans_, name, _ir)(DisasContext *ctx, \
2055+ cat3(arg_, name, _ir) * a) \
2056+ { \
2057+ TCGv mask; \
2058+ mask = tcg_const_i32(1 << a->imm); \
2059+ cat3(rx_, op, r)(cpu_regs[a->rd], mask); \
2060+ tcg_temp_free(mask); \
2061+ return true; \
2062+ } \
2063+ static bool cat3(trans_, name, _rr)(DisasContext *ctx, \
2064+ cat3(arg_, name, _rr) * a) \
2065+ { \
2066+ TCGv mask, b; \
2067+ mask = tcg_const_i32(1); \
2068+ b = tcg_temp_new(); \
2069+ tcg_gen_andi_i32(b, cpu_regs[a->rs], 31); \
2070+ tcg_gen_shl_i32(mask, mask, b); \
2071+ cat3(rx_, op, r)(cpu_regs[a->rd], mask); \
2072+ tcg_temp_free(mask); \
2073+ tcg_temp_free(b); \
2074+ return true; \
2075+ } \
2076+ static bool cat3(trans_, name, _rm)(DisasContext *ctx, \
2077+ cat3(arg_, name, _rm) * a) \
2078+ { \
2079+ TCGv mask, mem, addr, b; \
2080+ mask = tcg_const_i32(1); \
2081+ b = tcg_temp_new(); \
2082+ tcg_gen_andi_i32(b, cpu_regs[a->rd], 7); \
2083+ tcg_gen_shl_i32(mask, mask, b); \
2084+ mem = tcg_temp_new(); \
2085+ addr = rx_index_addr(ctx, mem, a->ld, MO_8, a->rs); \
2086+ cat3(rx_, op, m)(addr, mask); \
2087+ tcg_temp_free(mem); \
2088+ tcg_temp_free(mask); \
2089+ tcg_temp_free(b); \
2090+ return true; \
2091+ }
2092+
2093+BITOP(BSET, bset)
2094+BITOP(BCLR, bclr)
2095+BITOP(BTST, btst)
2096+BITOP(BNOT, bnot)
2097+
2098+static inline void bmcnd_op(TCGv val, TCGCond cond, int pos)
2099+{
2100+ TCGv bit;
2101+ DisasCompare dc;
2102+ dc.temp = tcg_temp_new();
2103+ bit = tcg_temp_new();
2104+ psw_cond(&dc, cond);
2105+ tcg_gen_andi_i32(val, val, ~(1 << pos));
2106+ tcg_gen_setcondi_i32(dc.cond, bit, dc.value, 0);
2107+ tcg_gen_deposit_i32(val, val, bit, pos, 1);
2108+ tcg_temp_free(bit);
2109+ tcg_temp_free(dc.temp);
2110+ }
2111+
2112+/* bmcnd #imm, dsp[rd] */
2113+static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a)
2114+{
2115+ TCGv val, mem, addr;
2116+ val = tcg_temp_new();
2117+ mem = tcg_temp_new();
2118+ addr = rx_index_addr(ctx, mem, a->ld, MO_8, a->rd);
2119+ rx_gen_ld(MO_8, val, addr);
2120+ bmcnd_op(val, a->cd, a->imm);
2121+ rx_gen_st(MO_8, val, addr);
2122+ tcg_temp_free(val);
2123+ tcg_temp_free(mem);
2124+ return true;
2125+}
2126+
2127+/* bmcond #imm, rd */
2128+static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a)
2129+{
2130+ bmcnd_op(cpu_regs[a->rd], a->cd, a->imm);
2131+ return true;
2132+}
2133+
2134+enum {
2135+ PSW_C = 0,
2136+ PSW_Z = 1,
2137+ PSW_S = 2,
2138+ PSW_O = 3,
2139+ PSW_I = 8,
2140+ PSW_U = 9,
2141+};
2142+
2143+static inline void clrsetpsw(DisasContext *ctx, int cb, int val)
2144+{
2145+ if (cb < 8) {
2146+ switch (cb) {
2147+ case PSW_C:
2148+ tcg_gen_movi_i32(cpu_psw_c, val);
2149+ break;
2150+ case PSW_Z:
2151+ tcg_gen_movi_i32(cpu_psw_z, val == 0);
2152+ break;
2153+ case PSW_S:
2154+ tcg_gen_movi_i32(cpu_psw_s, val ? -1 : 0);
2155+ break;
2156+ case PSW_O:
2157+ tcg_gen_movi_i32(cpu_psw_o, val << 31);
2158+ break;
2159+ default:
2160+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid distination %d", cb);
2161+ break;
2162+ }
2163+ } else if (is_privileged(ctx, 0)) {
2164+ switch (cb) {
2165+ case PSW_I:
2166+ tcg_gen_movi_i32(cpu_psw_i, val);
2167+ ctx->base.is_jmp = DISAS_UPDATE;
2168+ break;
2169+ case PSW_U:
2170+ tcg_gen_movi_i32(cpu_psw_u, val);
2171+ break;
2172+ default:
2173+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid distination %d", cb);
2174+ break;
2175+ }
2176+ }
2177+}
2178+
2179+/* clrpsw psw */
2180+static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a)
2181+{
2182+ clrsetpsw(ctx, a->cb, 0);
2183+ return true;
2184+}
2185+
2186+/* setpsw psw */
2187+static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a)
2188+{
2189+ clrsetpsw(ctx, a->cb, 1);
2190+ return true;
2191+}
2192+
2193+/* mvtipl #imm */
2194+static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a)
2195+{
2196+ if (is_privileged(ctx, 1)) {
2197+ tcg_gen_movi_i32(cpu_psw_ipl, a->imm);
2198+ ctx->base.is_jmp = DISAS_UPDATE;
2199+ }
2200+ return true;
2201+}
2202+
2203+/* mvtc #imm, rd */
2204+static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a)
2205+{
2206+ TCGv imm;
2207+
2208+ imm = tcg_const_i32(a->imm);
2209+ move_to_cr(ctx, imm, a->cr);
2210+ if (a->cr == 0 && is_privileged(ctx, 0)) {
2211+ ctx->base.is_jmp = DISAS_UPDATE;
2212+ }
2213+ tcg_temp_free(imm);
2214+ return true;
2215+}
2216+
2217+/* mvtc rs, rd */
2218+static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a)
2219+{
2220+ move_to_cr(ctx, cpu_regs[a->rs], a->cr);
2221+ if (a->cr == 0 && is_privileged(ctx, 0)) {
2222+ ctx->base.is_jmp = DISAS_UPDATE;
2223+ }
2224+ return true;
2225+}
2226+
2227+/* mvfc rs, rd */
2228+static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a)
2229+{
2230+ move_from_cr(cpu_regs[a->rd], a->cr, ctx->pc);
2231+ return true;
2232+}
2233+
2234+/* rtfi */
2235+static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a)
2236+{
2237+ TCGv psw;
2238+ if (is_privileged(ctx, 1)) {
2239+ psw = tcg_temp_new();
2240+ tcg_gen_mov_i32(cpu_pc, cpu_bpc);
2241+ tcg_gen_mov_i32(psw, cpu_bpsw);
2242+ gen_helper_set_psw_rte(cpu_env, psw);
2243+ ctx->base.is_jmp = DISAS_EXIT;
2244+ tcg_temp_free(psw);
2245+ }
2246+ return true;
2247+}
2248+
2249+/* rte */
2250+static bool trans_RTE(DisasContext *ctx, arg_RTE *a)
2251+{
2252+ TCGv psw;
2253+ if (is_privileged(ctx, 1)) {
2254+ psw = tcg_temp_new();
2255+ pop(cpu_pc);
2256+ pop(psw);
2257+ gen_helper_set_psw_rte(cpu_env, psw);
2258+ ctx->base.is_jmp = DISAS_EXIT;
2259+ tcg_temp_free(psw);
2260+ }
2261+ return true;
2262+}
2263+
2264+/* brk */
2265+static bool trans_BRK(DisasContext *ctx, arg_BRK *a)
2266+{
2267+ tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2268+ gen_helper_rxbrk(cpu_env);
2269+ ctx->base.is_jmp = DISAS_NORETURN;
2270+ return true;
2271+}
2272+
2273+/* int #imm */
2274+static bool trans_INT(DisasContext *ctx, arg_INT *a)
2275+{
2276+ TCGv vec;
2277+
2278+ tcg_debug_assert(a->imm < 0x100);
2279+ vec = tcg_const_i32(a->imm);
2280+ tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2281+ gen_helper_rxint(cpu_env, vec);
2282+ tcg_temp_free(vec);
2283+ ctx->base.is_jmp = DISAS_NORETURN;
2284+ return true;
2285+}
2286+
2287+/* wait */
2288+static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a)
2289+{
2290+ if (is_privileged(ctx, 1)) {
2291+ tcg_gen_addi_i32(cpu_pc, cpu_pc, 2);
2292+ gen_helper_wait(cpu_env);
2293+ }
2294+ return true;
2295+}
2296+
2297+static void rx_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2298+{
2299+ CPURXState *env = cs->env_ptr;
2300+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
2301+ ctx->env = env;
2302+}
2303+
2304+static void rx_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
2305+{
2306+}
2307+
2308+static void rx_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
2309+{
2310+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
2311+
2312+ tcg_gen_insn_start(ctx->base.pc_next);
2313+}
2314+
2315+static bool rx_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
2316+ const CPUBreakpoint *bp)
2317+{
2318+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
2319+
2320+ /* We have hit a breakpoint - make sure PC is up-to-date */
2321+ tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2322+ gen_helper_debug(cpu_env);
2323+ ctx->base.is_jmp = DISAS_NORETURN;
2324+ ctx->base.pc_next += 1;
2325+ return true;
2326+}
2327+
2328+static void rx_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
2329+{
2330+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
2331+ uint32_t insn;
2332+
2333+ ctx->pc = ctx->base.pc_next;
2334+ insn = decode_load(ctx);
2335+ if (!decode(ctx, insn)) {
2336+ gen_helper_raise_illegal_instruction(cpu_env);
2337+ }
2338+}
2339+
2340+static void rx_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
2341+{
2342+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
2343+
2344+ switch (ctx->base.is_jmp) {
2345+ case DISAS_NEXT:
2346+ case DISAS_TOO_MANY:
2347+ gen_goto_tb(ctx, 0, dcbase->pc_next);
2348+ break;
2349+ case DISAS_JUMP:
2350+ if (ctx->base.singlestep_enabled) {
2351+ gen_helper_debug(cpu_env);
2352+ } else {
2353+ tcg_gen_lookup_and_goto_ptr();
2354+ }
2355+ break;
2356+ case DISAS_UPDATE:
2357+ tcg_gen_movi_i32(cpu_pc, ctx->base.pc_next);
2358+ case DISAS_EXIT:
2359+ tcg_gen_exit_tb(NULL, 0);
2360+ break;
2361+ case DISAS_NORETURN:
2362+ break;
2363+ default:
2364+ g_assert_not_reached();
2365+ }
2366+}
2367+
2368+static void rx_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
2369+{
2370+ qemu_log("IN:\n"); /* , lookup_symbol(dcbase->pc_first)); */
2371+ log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
2372+}
2373+
2374+static const TranslatorOps rx_tr_ops = {
2375+ .init_disas_context = rx_tr_init_disas_context,
2376+ .tb_start = rx_tr_tb_start,
2377+ .insn_start = rx_tr_insn_start,
2378+ .breakpoint_check = rx_tr_breakpoint_check,
2379+ .translate_insn = rx_tr_translate_insn,
2380+ .tb_stop = rx_tr_tb_stop,
2381+ .disas_log = rx_tr_disas_log,
2382+};
2383+
2384+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
2385+{
2386+ DisasContext dc;
2387+
2388+ translator_loop(&rx_tr_ops, &dc.base, cs, tb, max_insns);
2389+}
2390+
2391+void restore_state_to_opc(CPURXState *env, TranslationBlock *tb,
2392+ target_ulong *data)
2393+{
2394+ env->pc = data[0];
2395+}
2396+
2397+#define ALLOC_REGISTER(sym, name) \
2398+ cpu_##sym = tcg_global_mem_new_i32(cpu_env, \
2399+ offsetof(CPURXState, sym), name)
2400+
2401+void rx_translate_init(void)
2402+{
2403+ static const char * const regnames[NUM_REGS] = {
2404+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
2405+ "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"
2406+ };
2407+ int i;
2408+
2409+ for (i = 0; i < NUM_REGS; i++) {
2410+ cpu_regs[i] = tcg_global_mem_new_i32(cpu_env,
2411+ offsetof(CPURXState, regs[i]),
2412+ regnames[i]);
2413+ }
2414+ ALLOC_REGISTER(pc, "PC");
2415+ ALLOC_REGISTER(psw_o, "PSW(O)");
2416+ ALLOC_REGISTER(psw_s, "PSW(S)");
2417+ ALLOC_REGISTER(psw_z, "PSW(Z)");
2418+ ALLOC_REGISTER(psw_c, "PSW(C)");
2419+ ALLOC_REGISTER(psw_u, "PSW(U)");
2420+ ALLOC_REGISTER(psw_i, "PSW(I)");
2421+ ALLOC_REGISTER(psw_pm, "PSW(PM)");
2422+ ALLOC_REGISTER(psw_ipl, "PSW(IPL)");
2423+ ALLOC_REGISTER(usp, "USP");
2424+ ALLOC_REGISTER(fpsw, "FPSW");
2425+ ALLOC_REGISTER(bpsw, "BPSW");
2426+ ALLOC_REGISTER(bpc, "BPC");
2427+ ALLOC_REGISTER(isp, "ISP");
2428+ ALLOC_REGISTER(fintv, "FINTV");
2429+ ALLOC_REGISTER(intb, "INTB");
2430+ cpu_acc = tcg_global_mem_new_i64(cpu_env,
2431+ offsetof(CPURXState, acc), "ACC");
2432+}