filename | src/sh4/sh4xir.in |
changeset | 1012:0b8cc74ac83a |
prev | 1011:fdd58619b760 |
author | nkeynes |
date | Sun Apr 19 05:14:19 2009 +0000 (15 years ago) |
branch | xlat-refactor |
permissions | -rw-r--r-- |
last change | Remove branch instructions and replace with direct modification of PC + EXIT Add MIN/MAX instructions (for bound checks) Implement x86_target_is_legal Correct a few sh4 instructions |
view | annotate | diff | log | raw |
1 /**
2 * $Id: sh4xir.in 931 2008-10-31 02:57:59Z nkeynes $
3 *
4 * SH4 => IR conversion.
5 *
6 * Copyright (c) 2009 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include <assert.h>
21 #include "sh4/sh4core.h"
22 #include "sh4/mmu.h"
23 #include "sh4/sh4xir.h"
24 #include "xlat/xlat.h"
25 #include "clock.h"
27 #define REG_OFFSET(reg) (offsetof( struct sh4_registers, reg))
29 #define R_R(rn) REG_OFFSET(r[rn])
30 #define R_R0 R_R(0)
31 #define R_SR REG_OFFSET(sr)
32 #define R_PR REG_OFFSET(pr)
33 #define R_PC REG_OFFSET(pc)
34 #define R_FPUL REG_OFFSET(fpul)
35 #define R_T REG_OFFSET(t)
36 #define R_M REG_OFFSET(m)
37 #define R_Q REG_OFFSET(q)
38 #define R_S REG_OFFSET(s)
39 #define R_FR(frn) REG_OFFSET(fr[0][(frn)^1])
40 #define R_DR(frn) REG_OFFSET(fr[0][(frn)&0x0E])
41 #define R_DRL(f) REG_OFFSET(fr[(f)&1][(f)|0x01])
42 #define R_DRH(f) REG_OFFSET(fr[(f)&1][(f)&0x0E])
43 #define R_XF(frn) REG_OFFSET(fr[1][(frn)^1])
44 #define R_XD(frn) REG_OFFSET(fr[1][(frn)&0x0E])
45 #define R_FV(fvn) REG_OFFSET(fr[0][fvn<<2])
46 #define R_XMTRX R_XD(0)
47 #define R_FPSCR REG_OFFSET(fpscr)
48 #define R_MAC REG_OFFSET(mac)
49 #define R_MACL REG_OFFSET(mac)
50 #define R_MACH REG_OFFSET(mac)+4
51 #define R_GBR REG_OFFSET(gbr)
52 #define R_SSR REG_OFFSET(ssr)
53 #define R_SPC REG_OFFSET(spc)
54 #define R_SGR REG_OFFSET(sgr)
55 #define R_DBR REG_OFFSET(dbr)
56 #define R_VBR REG_OFFSET(vbr)
57 #define R_BANK(rn) REG_OFFSET(r_bank[rn])
58 #define R_NEW_PC REG_OFFSET(new_pc)
59 #define R_DELAY_SLOT REG_OFFSET(in_delay_slot)
60 #define R_SLICE_CYCLE REG_OFFSET(slice_cycle)
61 #define R_SH4_MODE REG_OFFSET(xlat_sh4_mode)
63 uint32_t sh4_decode_basic_block(xir_basic_block_t xbb);
65 static const char *sh4_register_names[] =
66 {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
67 "sr", "pr", "pc", "fpul", "T", "M", "Q", "S",
68 "fr1", "fr0", "fr3", "fr2", "fr5", "fr4", "fr7", "fr6", "fr9", "fr8", "fr11", "fr10", "fr13", "fr11", "fr15", "fr14",
69 "xf1", "xf0", "xf3", "xf2", "xf5", "xf4", "xf7", "xf6", "xf9", "xf8", "xf11", "xf10", "xf13", "xf11", "xf15", "xf14",
70 "fpscr", 0, "macl", "mach", "gbr", "ssr", "spc", "sgr", "dbr", "vbr",
71 "r_bank0", "r_bank1", "r_bank2", "r_bank3", "r_bank4", "r_bank5", "r_bank6", "r_bank7",
72 "store_queue", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 "new_pc", "event_pending", "event_type", "delay_slot", "slice_cycle", "bus_cycle", "state", "xlat_mode" };
75 static const char *sh4_quad_register_names[] = /* From FR1 to MACH */
76 {"dr0", "dr2", "dr4", "dr6", "dr8", "dr10", "dr12", "dr14",
77 "xd0", "xd2", "xd4", "xd6", "xd8", "xd10", "xd12", "xd14",
78 NULL, "mac" };
79 static const char *sh4_vec4_register_names[] = /* From FR1 to XF14 */
80 {"fv0", "fv4", "fv8", "fv12", "xfv0", "xfv4", "xfv8", "xfv12" };
82 static const char *sh4_get_register_name( uint32_t reg, xir_type_t ty )
83 {
84 switch( ty ) {
85 case XTY_LONG:
86 case XTY_FLOAT:
87 if( reg <= R_SH4_MODE ) {
88 return sh4_register_names[reg>>2];
89 }
90 break;
91 case XTY_QUAD:
92 case XTY_DOUBLE:
93 if( reg >= R_DR(0) && reg <= R_MACH ) {
94 return sh4_quad_register_names[(reg-R_DR(0))>>3];
95 }
96 break;
97 case XTY_VEC4F:
98 if( reg >= R_DR(0) && reg <= R_XD(14) ) {
99 return sh4_vec4_register_names[(reg-R_DR(0))>>4];
100 }
101 break;
102 case XTY_MAT16F:
103 if( reg = R_XMTRX ) {
104 return "xmtrx";
105 } else if( reg == R_DR(0) ) {
106 return "mtrx";
107 }
108 }
109 return NULL;
110 }
112 struct xlat_source_machine sh4_source_machine = { "SH4", &sh4r,
113 R_PC, R_NEW_PC, R_T, R_M, R_Q, R_S,
114 sh4_get_register_name,
115 sh4_decode_basic_block };
117 /**
118 * Struct to manage internal translation state. This state is not saved -
119 * it is only valid between calls to sh4_translate_begin_block() and
120 * sh4_translate_end_block()
121 */
122 struct sh4_xir_state {
123 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */
124 gboolean double_prec; /* true if FPU is in double-precision mode */
125 gboolean double_size; /* true if FPU is in double-size mode */
126 };
128 static struct sh4_xir_state sh4_xir;
130 /**
131 * Create a standard exception-taking stub sub-block - updates SPC, slice_cycle, and exits
132 * @return the first xir_op_t of the exception block.
133 */
134 static inline xir_op_t write_exc( xir_basic_block_t xbb, sh4addr_t pc, int exc_code )
135 {
136 xir_op_t start = xbb->ir_ptr;
137 XOPCALL1I( sh4_raise_exception, exc_code );
138 if( pc != xbb->pc_begin ) {
139 XOP2IS( OP_ADD, pc - xbb->pc_begin, R_SPC );
140 }
141 XOP2IS( OP_ADD, (pc+2 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
142 XOP0( OP_EXIT )->next = NULL;
143 start->prev = NULL;
144 return start;
145 }
147 /**
148 * Create an instruction with a standard post-exception stub sub-block (ie
149 * sh4_raise_exception or similar has already been called - update SPC +
150 * slice_cycle and exit).
151 * @return the first xir_op_t of the exception block.
152 */
153 static xir_op_t xir_append_op2_exc( xir_basic_block_t xbb, int op, int arg0form, uint32_t arg0, int arg1form, uint32_t arg1, sh4addr_t pc )
154 {
155 xir_op_t ins = xir_append_op2( xbb, op, arg0form, arg0, arg1form, arg1 );
156 ins->exc = xbb->ir_ptr;
157 ins->exc->prev = ins;
159 if( pc != xbb->pc_begin ) {
160 XOP2IS( OP_ADD, pc - xbb->pc_begin, R_SPC );
161 }
162 XOP2IS( OP_ADD, (pc+2 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
163 XOP0( OP_EXIT )->next = NULL;
165 ins->next = xbb->ir_ptr;
166 xbb->ir_ptr->prev = ins;
167 return ins;
168 }
170 #define XOP1SE( op, arg0 ) xir_append_op2_exc( xbb, op, SOURCE_OPERAND, arg0, NO_OPERAND, 0, (in_delay_slot ? pc-2 : pc))
171 #define XOP1TE( op, arg0 ) xir_append_op2_exc( xbb, op, TEMP_OPERAND, arg0, NO_OPERAND, 0, (in_delay_slot ? pc-2 : pc))
172 #define XOP2SSE( op, arg0, arg1 ) xir_append_op2_exc( xbb, op, SOURCE_OPERAND, arg0, SOURCE_OPERAND, arg1, (in_delay_slot ? pc-2 : pc))
173 #define XOP2STE( op, arg0, arg1 ) xir_append_op2_exc( xbb, op, SOURCE_OPERAND, arg0, TEMP_OPERAND, arg1, (in_delay_slot ? pc-2 : pc))
174 #define XOP2TSE( op, arg0, arg1 ) xir_append_op2_exc( xbb, op, TEMP_OPERAND, arg0, SOURCE_OPERAND, arg1, (in_delay_slot ? pc-2 : pc))
175 #define XOP2TTE( op, arg0, arg1 ) xir_append_op2_exc( xbb, op, TEMP_OPERAND, arg0, TEMP_OPERAND, arg1, (in_delay_slot ? pc-2 : pc))
177 #define ALIGN(m,r,code) do { \
178 xir_op_t ins = xir_append_op2(xbb, OP_RAISEMNE, IMMEDIATE_OPERAND, m, SOURCE_OPERAND, r); \
179 ins->exc = write_exc(xbb, (in_delay_slot ? pc-2 : pc), code); \
180 ins->exc->prev = ins; \
181 ins->next = xbb->ir_ptr; \
182 xbb->ir_ptr->prev = ins; \
183 } while(0)
185 #define SLOTILLEGAL() write_exc(xbb, pc, EXC_SLOT_ILLEGAL)
186 #define ILLEGAL() write_exc(xbb, pc, EXC_ILLEGAL)
188 #define UNDEF(ir) if( in_delay_slot ) { SLOTILLEGAL(); return 2; } else { ILLEGAL(); return 2; }
189 #define CHECKFPUEN() if( !sh4_xir.fpuen_checked ) { \
190 xir_op_t ins = XOP2IS( OP_RAISEMNE, SR_FD, R_SR ); \
191 if( in_delay_slot ) { \
192 ins->exc = write_exc(xbb, pc-2, EXC_SLOT_FPU_DISABLED); \
193 } else { \
194 ins->exc = write_exc(xbb, pc, EXC_FPU_DISABLED); \
195 } \
196 ins->exc->prev = ins; \
197 ins->next = xbb->ir_ptr; \
198 xbb->ir_ptr->prev = ins; \
199 sh4_xir.fpuen_checked = TRUE; \
200 }
201 #define CHECKPRIV() if( (sh4r.xlat_sh4_mode & SR_MD) == 0 ) { UNDEF(ir); }
203 #define RALIGN16(r) ALIGN(0x01,r,EXC_DATA_ADDR_READ)
204 #define RALIGN32(r) ALIGN(0x03,r,EXC_DATA_ADDR_READ)
205 #define RALIGN64(r) ALIGN(0x07,r,EXC_DATA_ADDR_READ)
206 #define WALIGN16(r) ALIGN(0x01,r,EXC_DATA_ADDR_WRITE)
207 #define WALIGN32(r) ALIGN(0x03,r,EXC_DATA_ADDR_WRITE)
208 #define WALIGN64(r) ALIGN(0x07,r,EXC_DATA_ADDR_WRITE)
210 #define UNTRANSLATABLE(pc) !IS_IN_ICACHE(pc)
212 #define EMU_DELAY_SLOT() do { \
213 XOP2IS( OP_ADD, (pc+2 - xbb->pc_begin), R_PC ); \
214 XOP2IS( OP_MOV, 1, R_DELAY_SLOT ); \
215 XOP0( OP_BARRIER ); \
216 XOPCALL0( sh4_execute_instruction ); \
217 XOP0( OP_EXIT ); \
218 } while(0)
221 static sh4addr_t sh4_decode_instruction( xir_basic_block_t xbb, sh4addr_t pc, gboolean in_delay_slot )
222 {
223 assert( IS_IN_ICACHE(pc) );
224 uint16_t ir = *(uint16_t *)GET_ICACHE_PTR(pc);
226 %%
227 ADD Rm, Rn {: XOP2SS( OP_ADD, R_R(Rm), R_R(Rn) ); :}
228 ADD #imm, Rn {: XOP2IS( OP_ADD, imm, R_R(Rn) ); :}
229 ADDC Rm, Rn {:
230 XOP1SCC( OP_LD, CC_C, R_T );
231 XOP2SS( OP_ADDCS, R_R(Rm), R_R(Rn) );
232 XOP1SCC( OP_ST, CC_C, R_T );
233 :}
234 ADDV Rm, Rn {: XOP2SS( OP_ADDS, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_OV, R_T ); :}
235 AND Rm, Rn {: XOP2SS( OP_AND, R_R(Rm), R_R(Rn) ); :}
236 AND #imm, R0 {: XOP2IS( OP_AND, imm, R_R0 ); :}
237 CMP/EQ Rm, Rn {: XOP2SS( OP_CMP, Rm, R_R(Rn) ); XOP1SCC( OP_ST, CC_EQ, R_T ); :}
238 CMP/EQ #imm, R0 {: XOP2IS( OP_CMP, imm, R_R0 ); XOP1SCC( OP_ST, CC_EQ, R_T ); :}
239 CMP/GE Rm, Rn {: XOP2SS( OP_CMP, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_SGE, R_T ); :}
240 CMP/GT Rm, Rn {: XOP2SS( OP_CMP, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_SGT, R_T ); :}
241 CMP/HI Rm, Rn {: XOP2SS( OP_CMP, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_UGT, R_T ); :}
242 CMP/HS Rm, Rn {: XOP2SS( OP_CMP, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_UGE, R_T ); :}
243 CMP/PL Rn {: XOP2IS( OP_CMP, 0, R_R(Rn) ); XOP1SCC( OP_ST, CC_SGT, R_T ); :}
244 CMP/PZ Rn {: XOP2IS( OP_CMP, 0, R_R(Rn) ); XOP1SCC( OP_ST, CC_SGE, R_T ); :}
245 CMP/STR Rm, Rn {: XOP2SS( OP_CMPSTR, R_R(Rm), R_R(Rn) ); :}
246 DIV0S Rm, Rn {:
247 XOP2SS( OP_MOV, R_R(Rm), R_M );
248 XOP2IS( OP_SLR, 31, R_M );
249 XOP2SS( OP_MOV, R_R(Rn), R_Q );
250 XOP2IS( OP_SLR, 31, R_Q );
251 XOP2SS( OP_CMP, R_M, R_Q );
252 XOP1SCC( OP_ST, CC_NE, R_T );
253 :}
254 DIV0U {:
255 XOP2IS( OP_MOV, 0, R_M );
256 XOP2IS( OP_MOV, 0, R_Q );
257 XOP2IS( OP_MOV, 0, R_T );
258 :}
259 DIV1 Rm, Rn {: XOP2SS( OP_DIV1, R_R(Rm), R_R(Rn) ); :}
260 DMULS.L Rm, Rn {:
261 XOP2SS( OP_MOVSX32, R_R(Rm), R_MAC );
262 XOP2ST( OP_MOVSX32, R_R(Rn), REG_TMP0 );
263 XOP2TS( OP_MULQ, REG_TMPQ0, R_MAC );
264 :}
265 DMULU.L Rm, Rn {:
266 XOP2SS( OP_MOVZX32, R_R(Rm), R_MAC );
267 XOP2ST( OP_MOVZX32, R_R(Rn), REG_TMP0 ) ;
268 XOP2TS( OP_MULQ, REG_TMP0, R_MAC );
269 :}
270 DT Rn {: XOP1S( OP_DEC, R_R(Rn) ); :}
271 EXTS.B Rm, Rn {: XOP2SS( OP_MOVSX8, R_R(Rm), R_R(Rn)); :}
272 EXTS.W Rm, Rn {: XOP2SS( OP_MOVSX16, R_R(Rm), R_R(Rn)); :}
273 EXTU.B Rm, Rn {: XOP2SS( OP_MOVZX8, R_R(Rm), R_R(Rn)); :}
274 EXTU.W Rm, Rn {: XOP2SS( OP_MOVZX16, R_R(Rm), R_R(Rn)); :}
275 MAC.L @Rm+, @Rn+ {:
276 RALIGN32(R_R(Rm));
277 if( Rm == Rn ) {
278 XOP2STE( OP_LOADL, R_R(Rm), REG_TMP0 );
279 XOP2ST( OP_MOV, R_R(Rm), REG_TMP1 );
280 XOP2IT( OP_ADD, 4, REG_TMP1 );
281 XOP2TTE( OP_LOADL, REG_TMP1, REG_TMP1 );
282 XOP2IS( OP_ADD, 8, R_R(Rm) );
283 } else {
284 RALIGN32(R_R(Rn));
285 XOP2STE( OP_LOADL, R_R(Rm), REG_TMP0 );
286 XOP2STE( OP_LOADL, R_R(Rn), REG_TMP1 );
287 XOP2IS( OP_ADD, 4, R_R(Rm) );
288 XOP2IS( OP_ADD, 4, R_R(Rn) );
289 }
290 XOP2TT( OP_MOVSX32, REG_TMP0, REG_TMPQ0 );
291 XOP2TT( OP_MOVSX32, REG_TMP1, REG_TMPQ1 );
292 XOP2TT( OP_MULQ, REG_TMPQ0, REG_TMPQ1 );
293 XOP2TS( OP_ADDQSAT48, REG_TMPQ1, R_MAC );
294 :}
295 MAC.W @Rm+, @Rn+ {:
296 RALIGN32(R_R(Rm));
297 if( Rm == Rn ) {
298 XOP2STE( OP_LOADW, R_R(Rm), REG_TMP0 );
299 XOP2ST( OP_MOV, R_R(Rm), REG_TMP1 );
300 XOP2IT( OP_ADD, 2, REG_TMP1 );
301 XOP2TTE( OP_LOADW, REG_TMP1, REG_TMP1 );
302 XOP2IS( OP_ADD, 4, R_R(Rm) );
303 } else {
304 RALIGN32(Rn);
305 XOP2STE( OP_LOADW, R_R(Rm), REG_TMP0 );
306 XOP2STE( OP_LOADW, R_R(Rn), REG_TMP1 );
307 XOP2IS( OP_ADD, 2, R_R(Rm) );
308 XOP2IS( OP_ADD, 2, R_R(Rn) );
309 }
310 XOP2TT( OP_MOVSX32, REG_TMP0, REG_TMPQ0 );
311 XOP2TT( OP_MOVSX32, REG_TMP1, REG_TMPQ1 );
312 XOP2TT( OP_MULQ, REG_TMPQ0, REG_TMPQ1 );
313 XOP2TS( OP_ADDQSAT32, REG_TMPQ1, R_MAC );
314 :}
315 MOVT Rn {: XOP2SS( OP_MOV, R_R(Rn), R_T ); :}
316 MUL.L Rm, Rn {:
317 XOP2SS( OP_MOV, R_R(Rm), R_MACL );
318 XOP2SS( OP_MUL, R_R(Rn), R_MACL );
319 :}
320 MULS.W Rm, Rn {:
321 XOP2ST( OP_MOVSX16, R_R(Rm), REG_TMP0 );
322 XOP2SS( OP_MOVSX16, R_R(Rn), R_MACL );
323 XOP2TS( OP_MUL, REG_TMP0, R_MACL );
324 :}
325 MULU.W Rm, Rn {:
326 XOP2ST( OP_MOVZX16, R_R(Rm), REG_TMP0 );
327 XOP2SS( OP_MOVZX16, R_R(Rn), R_MACL );
328 XOP2TS( OP_MUL, REG_TMP0, R_MACL );
329 :}
330 NEG Rm, Rn {:
331 XOP2SS( OP_NEG, R_R(Rm), R_R(Rn) );
332 :}
333 NEGC Rm, Rn {:
334 XOP1SCC( OP_LD, CC_C, R_T );
335 if( Rm == Rn ) {
336 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
337 XOP2IS(OP_MOV, 0, R_R(Rn) );
338 XOP2TS( OP_SUBBS, REG_TMP0, R_R(Rn) );
339 } else {
340 XOP2IS(OP_MOV, 0, R_R(Rn) );
341 XOP2SS( OP_SUBBS, R_R(Rm), R_R(Rn) );
342 }
343 XOP1SCC( OP_ST, CC_C, R_T );
344 :}
345 NOT Rm, Rn {:
346 XOP2SS( OP_NOT, R_R(Rm), R_R(Rn) );
347 :}
348 OR Rm, Rn {: XOP2SS( OP_OR, R_R(Rm), R_R(Rn) ); :}
349 OR #imm, R0 {: XOP2IS( OP_OR, imm, R_R0 ); :}
350 ROTCL Rn {: XOP1SCC( OP_LD, CC_C, R_T ); XOP2IS( OP_RCL, 1, R_R(Rn) ); XOP1SCC( OP_ST, CC_C, R_T); :}
351 ROTCR Rn {: XOP1SCC( OP_LD, CC_C, R_T ); XOP2IS( OP_RCR, 1, R_R(Rn) ); XOP1SCC( OP_ST, CC_C, R_T); :}
352 ROTL Rn {: XOP2IS( OP_ROL, 1, R_R(Rn) ); :}
353 ROTR Rn {: XOP2IS( OP_ROR, 1, R_R(Rn) ); :}
354 SHAD Rm, Rn {: XOP2SS( OP_SHAD, R_R(Rm), R_R(Rn) ); :}
355 SHLD Rm, Rn {: XOP2SS( OP_SHLD, R_R(Rm), R_R(Rn) ); :}
356 SHAL Rn {: XOP2IS( OP_SLLS, 1, R_R(Rn) ); XOP1SCC( OP_ST, CC_C, R_T); :}
357 SHAR Rn {: XOP2IS( OP_SARS, 1, R_R(Rn) ); XOP1SCC( OP_ST, CC_C, R_T); :}
358 SHLL Rn {: XOP2IS( OP_SLLS, 1, R_R(Rn) ); XOP1SCC( OP_ST, CC_C, R_T); :}
359 SHLL2 Rn {: XOP2IS( OP_SLL, 2, R_R(Rn) ); :}
360 SHLL8 Rn {: XOP2IS( OP_SLL, 8, R_R(Rn) ); :}
361 SHLL16 Rn {: XOP2IS( OP_SLL, 16, R_R(Rn) ); :}
362 SHLR Rn {: XOP2IS( OP_SLRS, 1, R_R(Rn) ); XOP1SCC( OP_ST, CC_C, R_T); :}
363 SHLR2 Rn {: XOP2IS( OP_SLR, 2, R_R(Rn) ); :}
364 SHLR8 Rn {: XOP2IS( OP_SLR, 8, R_R(Rn) ); :}
365 SHLR16 Rn {: XOP2IS( OP_SLR, 16, R_R(Rn) ); :}
366 SUB Rm, Rn {:
367 if( Rm == Rn ) {
368 /* Break false dependence */
369 XOP2IS( OP_MOV, 0, R_R(Rn) );
370 } else {
371 XOP2SS( OP_SUB, R_R(Rm), R_R(Rn) );
372 }
373 :}
374 SUBC Rm, Rn {: XOP1SCC( OP_LD, CC_C, R_T ); XOP2SS( OP_SUBBS, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_C, R_T ); :}
375 SUBV Rm, Rn {: XOP2SS( OP_SUB, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_OV, R_T ); :}
376 SWAP.B Rm, Rn {:
377 if( Rm != Rn ) {
378 XOP2SS( OP_MOV, R_R(Rm), R_R(Rn) );
379 }
380 XOP2IS( OP_SHUFFLE, 0x1243, R_R(Rn) );
381 :}
382 SWAP.W Rm, Rn {:
383 if( Rm != Rn ) {
384 XOP2SS( OP_MOV, R_R(Rm), R_R(Rn) );
385 }
386 XOP2IS( OP_SHUFFLE, 0x3412, R_R(Rn) );
387 :}
388 TST Rm, Rn {: XOP2SS( OP_TST, R_R(Rm), R_R(Rn) ); XOP1SCC( OP_ST, CC_EQ, R_T ); :}
389 TST #imm, R0 {: XOP2IS( OP_TST, imm, R_R0 ); XOP1SCC( OP_ST, CC_EQ, R_T ); :}
390 XOR Rm, Rn {:
391 if( Rm == Rn ) {
392 /* Break false dependence */
393 XOP2IS( OP_MOV, 0, R_R(Rn) );
394 } else {
395 XOP2SS( OP_XOR, R_R(Rm), R_R(Rn) );
396 }
397 :}
398 XOR #imm, R0 {: XOP2IS( OP_XOR, imm, R_R0 ); :}
399 XTRCT Rm, Rn {:
400 XOP2ST( OP_MOV, R_R(Rm), REG_TMP0 );
401 XOP2IT( OP_SLL, 16, REG_TMP0 );
402 XOP2IS( OP_SLR, 16, R_R(Rn) );
403 XOP2TS( OP_OR, REG_TMP0, R_R(Rn) );
404 :}
405 MOV Rm, Rn {: XOP2SS( OP_MOV, R_R(Rm), R_R(Rn) ); :}
406 MOV #imm, Rn {: XOP2IS( OP_MOV, imm, R_R(Rn) ); :}
408 AND.B #imm, @(R0, GBR) {:
409 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
410 XOP2ST( OP_ADD, R_GBR, REG_TMP0 );
411 XOP2TTE( OP_LOADBFW, REG_TMP0, REG_TMP1 );
412 XOP2IT( OP_AND, imm, REG_TMP1 );
413 XOP2TTE( OP_STOREB, REG_TMP0, REG_TMP1 );
414 :}
415 OR.B #imm, @(R0, GBR) {:
416 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
417 XOP2ST( OP_ADD, R_GBR, REG_TMP0 );
418 XOP2TTE( OP_LOADBFW, REG_TMP0, REG_TMP1 );
419 XOP2IT( OP_OR, imm, REG_TMP1 );
420 XOP2TTE( OP_STOREB, REG_TMP0, REG_TMP1 );
421 :}
422 TAS.B @Rn {:
423 XOP1S( OP_OCBP, R_R(Rn) );
424 XOP2STE( OP_LOADBFW, R_R(Rn), REG_TMP0 );
425 XOP2IT( OP_CMP, 0, REG_TMP0 );
426 XOP1SCC(OP_ST, CC_EQ, R_T );
427 XOP2IT( OP_OR, 0x80, REG_TMP0 );
428 XOP2STE( OP_STOREB, R_R(Rn), REG_TMP0 );
429 :}
430 TST.B #imm, @(R0, GBR) {:
431 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
432 XOP2ST( OP_ADD, R_GBR, REG_TMP0 );
433 XOP2TTE( OP_LOADB, REG_TMP0, REG_TMP0 );
434 XOP2IT( OP_TST, imm, REG_TMP0 );
435 :}
436 XOR.B #imm, @(R0, GBR) {:
437 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
438 XOP2ST( OP_ADD, R_GBR, REG_TMP0 );
439 XOP2TTE( OP_LOADBFW, REG_TMP0, REG_TMP1 );
440 XOP2IT( OP_XOR, imm, REG_TMP1 );
441 XOP2TTE( OP_STOREB, REG_TMP0, REG_TMP1 );
442 :}
444 MOV.B Rm, @Rn {:
445 XOP2SSE( OP_STOREB, R_R(Rn), R_R(Rm) );
446 :}
447 MOV.B Rm, @-Rn {:
448 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
449 XOP2IT( OP_ADD, -1, REG_TMP0 );
450 XOP2TSE( OP_STOREB, REG_TMP0, R_R(Rm) );
451 XOP2IS( OP_ADD, -1, R_R(Rn) );
452 :}
453 MOV.B Rm, @(R0, Rn) {:
454 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
455 XOP2ST( OP_ADD, R_R0, REG_TMP0 );
456 XOP2TSE( OP_STOREB, REG_TMP0, R_R(Rm) );
457 :}
458 MOV.B R0, @(disp, GBR) {:
459 XOP2ST( OP_MOV, R_GBR, REG_TMP0 );
460 XOP2IT( OP_ADD, disp, REG_TMP0 );
461 XOP2TSE( OP_STOREB, REG_TMP0, R_R0 );
462 :}
463 MOV.B R0, @(disp, Rn) {:
464 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
465 XOP2IT( OP_ADD, disp, REG_TMP0 );
466 XOP2TSE( OP_STOREB, REG_TMP0, R_R0 );
467 :}
468 MOV.B @Rm, Rn {:
469 XOP2SSE( OP_LOADB, R_R(Rm), R_R(Rn) );
470 :}
471 MOV.B @Rm+, Rn {:
472 XOP2SSE( OP_LOADB, R_R(Rm), R_R(Rn) );
473 if( Rm != Rn ) {
474 XOP2IS( OP_ADD, 1, R_R(Rm) );
475 }
476 :}
477 MOV.B @(R0, Rm), Rn {:
478 XOP2ST( OP_MOV, R_R(Rm), REG_TMP0 );
479 XOP2ST( OP_ADD, R_R0, REG_TMP0 );
480 XOP2TSE(OP_LOADB, REG_TMP0, R_R(Rn) );
481 :}
482 MOV.B @(disp, GBR), R0 {:
483 XOP2ST( OP_MOV, R_GBR, REG_TMP0 );
484 XOP2IT(OP_ADD, disp, REG_TMP0 );
485 XOP2TSE(OP_LOADB, REG_TMP0, R_R0 );
486 :}
487 MOV.B @(disp, Rm), R0 {:
488 XOP2ST( OP_MOV, R_R(Rm), REG_TMP0 );
489 XOP2IT(OP_ADD, disp, REG_TMP0 );
490 XOP2TSE(OP_LOADB, REG_TMP0, R_R0 );
491 :}
492 MOV.L Rm, @Rn {:
493 WALIGN32( R_R(Rn) );
494 XOP2SSE( OP_STOREL, R_R(Rn), R_R(Rm) );
495 :}
496 MOV.L Rm, @-Rn {:
497 WALIGN32( R_R(Rn) );
498 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
499 XOP2IT(OP_ADD, -4, REG_TMP0 );
500 XOP2TS( OP_STOREL, REG_TMP0, R_R(Rm) );
501 XOP2IS(OP_ADD, -4, R_R(Rn) );
502 :}
503 MOV.L Rm, @(R0, Rn) {:
504 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
505 XOP2ST( OP_ADD, R_R0, REG_TMP0 );
506 WALIGN32( REG_TMP0 );
507 XOP2TSE(OP_STOREL, REG_TMP0, R_R(Rm) );
508 :}
509 MOV.L R0, @(disp, GBR) {:
510 XOP2ST( OP_MOV, R_GBR, REG_TMP0 );
511 XOP2IT(OP_ADD, disp, REG_TMP0 );
512 WALIGN32( REG_TMP0 );
513 XOP2TSE(OP_STOREL, REG_TMP0, R_R0 );
514 :}
515 MOV.L Rm, @(disp, Rn) {:
516 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
517 XOP2IT(OP_ADD, disp, REG_TMP0 );
518 WALIGN32( REG_TMP0 );
519 XOP2TSE(OP_STOREL, REG_TMP0, R_R(Rm) );
520 :}
521 MOV.L @Rm, Rn {:
522 RALIGN32( R_R(Rm) );
523 XOP2SSE(OP_LOADL, R_R(Rm), R_R(Rn) );
524 :}
525 MOV.L @Rm+, Rn {:
526 RALIGN32( R_R(Rm) );
527 XOP2SSE( OP_LOADL, R_R(Rm), R_R(Rn) );
528 if( R_R(Rm) != R_R(Rn) ) {
529 XOP2IS( OP_ADD, 4, R_R(Rm) );
530 }
531 :}
532 MOV.L @(R0, Rm), Rn {:
533 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
534 XOP2ST( OP_ADD, R_R(Rm), REG_TMP0 );
535 RALIGN32( REG_TMP0 );
536 XOP2TSE(OP_LOADL, REG_TMP0, R_R(Rn) );
537 :}
538 MOV.L @(disp, GBR), R0 {:
539 XOP2ST( OP_MOV, R_GBR, REG_TMP0 );
540 XOP2IT(OP_ADD, disp, REG_TMP0 );
541 RALIGN32( REG_TMP0 );
542 XOP2TSE(OP_LOADL, REG_TMP0, R_R0 );
543 :}
544 MOV.L @(disp, PC), Rn {:
545 if( in_delay_slot ) {
546 SLOTILLEGAL();
547 return 2;
548 } else {
549 uint32_t target = (pc & 0xFFFFFFFC) + disp + 4;
550 if( IS_IN_ICACHE(target) ) {
551 // If the target address is in the same page as the code, it's
552 // pretty safe to just ref it directly and circumvent the whole
553 // memory subsystem. (this is a big performance win)
555 // FIXME: There's a corner-case that's not handled here when
556 // the current code-page is in the ITLB but not in the UTLB.
557 // (should generate a TLB miss although need to test SH4
558 // behaviour to confirm) Unlikely to be anyone depending on this
559 // behaviour though.
560 sh4ptr_t ptr = GET_ICACHE_PTR(target);
561 XOP2PS( OP_LOADPTRL, ptr, R_R(Rn) );
562 } else {
563 // Note: we use sh4r.pc for the calc as we could be running at a
564 // different virtual address than the translation was done with,
565 // but we can safely assume that the low bits are the same.
566 XOP2ST( OP_MOV, R_PC, REG_TMP0 );
567 XOP2IT( OP_ADD, (pc-xbb->pc_begin) + disp + 4 - (pc&0x03), REG_TMP0 );
568 XOP2TSE(OP_LOADL, REG_TMP0, R_R(Rn) );
569 }
570 }
571 :}
572 MOV.L @(disp, Rm), Rn {:
573 XOP2ST( OP_MOV, R_R(Rm), REG_TMP0 );
574 XOP2IT(OP_ADD, disp, REG_TMP0 );
575 RALIGN32( REG_TMP0 );
576 XOP2TSE(OP_LOADL, REG_TMP0, R_R(Rn) );
577 :}
578 MOV.W Rm, @Rn {:
579 WALIGN16( R_R(Rn) );
580 XOP2SSE(OP_STOREW, R_R(Rn), R_R(Rm) );
581 :}
582 MOV.W Rm, @-Rn {:
583 WALIGN16( R_R(Rn) );
584 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
585 XOP2IT(OP_ADD, -2, REG_TMP0 );
586 XOP2TSE(OP_STOREW, REG_TMP0, R_R(Rm) );
587 XOP2IS(OP_ADD, -2, R_R(Rn) );
588 :}
589 MOV.W Rm, @(R0, Rn) {:
590 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
591 XOP2ST( OP_ADD, R_R(Rn), REG_TMP0 );
592 WALIGN16( REG_TMP0 );
593 XOP2TSE(OP_STOREW, REG_TMP0, R_R(Rm) );
594 :}
595 MOV.W R0, @(disp, GBR) {:
596 XOP2ST( OP_MOV, R_GBR, REG_TMP0 );
597 XOP2IT(OP_ADD, disp, REG_TMP0 );
598 WALIGN16( REG_TMP0 );
599 XOP2TS( OP_STOREW, REG_TMP0, R_R0 );
600 :}
601 MOV.W R0, @(disp, Rn) {:
602 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
603 XOP2IT(OP_ADD, disp, REG_TMP0 );
604 WALIGN16( REG_TMP0 );
605 XOP2TSE(OP_STOREW, REG_TMP0, R_R0 );
606 :}
607 MOV.W @Rm, Rn {:
608 RALIGN16( R_R(Rm) );
609 XOP2SSE(OP_LOADW, R_R(Rm), R_R(Rn) );
610 :}
611 MOV.W @Rm+, Rn {:
612 RALIGN16( R_R(Rm) );
613 XOP2SSE(OP_LOADW, R_R(Rm), R_R(Rn) );
614 if( Rm != Rn ) {
615 XOP2IS( OP_ADD, 2, R_R(Rm) );
616 }
617 :}
618 MOV.W @(R0, Rm), Rn {:
619 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
620 XOP2ST( OP_ADD, R_R(Rm), REG_TMP0 );
621 RALIGN16( REG_TMP0 );
622 XOP2TSE(OP_LOADW, REG_TMP0, R_R(Rn) );
623 :}
624 MOV.W @(disp, GBR), R0 {:
625 XOP2ST( OP_MOV, R_GBR, REG_TMP0 );
626 XOP2IT(OP_ADD, disp, REG_TMP0 );
627 RALIGN16( REG_TMP0 );
628 XOP2TSE(OP_LOADW, REG_TMP0, R_R0 );
629 :}
630 MOV.W @(disp, PC), Rn {:
631 if( in_delay_slot ) {
632 SLOTILLEGAL();
633 return 2;
634 } else {
635 uint32_t target = pc + disp + 4;
636 if( IS_IN_ICACHE(target) ) {
637 // If the target address is in the same page as the code, it's
638 // pretty safe to just ref it directly and circumvent the whole
639 // memory subsystem. (this is a big performance win)
641 // FIXME: There's a corner-case that's not handled here when
642 // the current code-page is in the ITLB but not in the UTLB.
643 // (should generate a TLB miss although need to test SH4
644 // behaviour to confirm) Unlikely to be anyone depending on this
645 // behaviour though.
646 sh4ptr_t ptr = GET_ICACHE_PTR(target);
647 XOP2PT( OP_LOADPTRW, ptr, REG_TMP0 );
648 } else {
649 // Note: we use sh4r.pc for the calc as we could be running at a
650 // different virtual address than the translation was done with,
651 // but we can safely assume that the low bits are the same.
652 XOP2ST( OP_MOV, R_PC, REG_TMP0 );
653 XOP2IT( OP_ADD, (pc - xbb->pc_begin) + disp + 4, REG_TMP0 );
654 XOP2TSE(OP_LOADW, REG_TMP0, R_R(Rn) );
655 }
656 }
657 :}
658 MOV.W @(disp, Rm), R0 {:
659 XOP2ST( OP_MOV, R_R(Rm), REG_TMP0 );
660 XOP2IT(OP_ADD, disp, REG_TMP0 );
661 RALIGN16( REG_TMP0 );
662 XOP2TSE(OP_LOADW, REG_TMP0, R_R0 );
663 :}
664 MOVA @(disp, PC), R0 {:
665 if( in_delay_slot ) {
666 SLOTILLEGAL();
667 return 2;
668 } else {
669 XOP2SS( OP_MOV, R_PC, R_R0 );
670 XOP2IS( OP_ADD, (pc - xbb->pc_begin) + disp + 4 - (pc&0x03), R_R0 );
671 }
672 :}
673 MOVCA.L R0, @Rn {:
674 XOP2SSE(OP_STORELCA, R_R(Rn), R_R0 );
675 :}
676 LDTLB {:
677 CHECKPRIV();
678 XOPCALL0( MMU_ldtlb );
679 :}
680 OCBI @Rn {: XOP1SE( OP_OCBI, R_R(Rn) ); :}
681 OCBP @Rn {: XOP1SE( OP_OCBP, R_R(Rn) ); :}
682 OCBWB @Rn {: XOP1SE( OP_OCBWB, R_R(Rn) ); :}
683 PREF @Rn {: XOP1SE( OP_PREF, R_R(Rn) ); :}
685 CLRMAC {:
686 XOP2IS( OP_MOV, 0, R_MACL );
687 XOP2IS( OP_MOV, 0, R_MACH );
688 :}
689 CLRS {: XOP2IS( OP_MOV, 0, R_S ); :}
690 CLRT {: XOP2IS( OP_MOV, 0, R_T ); :}
691 SETS {: XOP2IS( OP_MOV, 1, R_S ); :}
692 SETT {: XOP2IS( OP_MOV, 1, R_T ); :}
693 FMOV FRm, FRn {:
694 CHECKFPUEN();
695 if( sh4_xir.double_size ) {
696 XOP2SS( OP_MOVQ, (FRm&1) ? R_XD(FRm) : R_DR(FRm), (FRn&1) ? R_XD(FRn) : R_DR(FRn) );
697 } else {
698 XOP2SS( OP_MOV, R_FR(FRm), R_FR(FRn) );
699 }
700 :}
701 FMOV FRm, @Rn {:
702 CHECKFPUEN();
703 if( sh4_xir.double_size ) {
704 WALIGN64( R_R(Rn) );
705 XOP2SSE( OP_STOREQ, R_R(Rn), (FRm&1) ? R_XD(FRm) : R_DR(FRm) );
706 } else {
707 WALIGN32( R_R(Rn) );
708 XOP2SSE( OP_STOREL, R_R(Rn), R_FR(FRm) );
709 }
710 :}
711 FMOV @Rm, FRn {:
712 CHECKFPUEN();
713 if( sh4_xir.double_size ) {
714 RALIGN64( R_R(Rm) );
715 XOP2SSE( OP_LOADQ, R_R(Rm), (FRn&1) ? R_XD(FRn) : R_DR(FRn) );
716 } else {
717 RALIGN32( R_R(Rm) );
718 XOP2SSE( OP_LOADL, R_R(Rm), R_FR(FRn) );
719 }
720 :}
721 FMOV FRm, @-Rn {:
722 CHECKFPUEN();
723 if( sh4_xir.double_size ) {
724 WALIGN64( R_R(Rn) );
725 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
726 XOP2IT(OP_ADD, -8, REG_TMP0 );
727 XOP2TSE(OP_STOREQ, REG_TMP0, (FRm&1) ? R_XD(FRm) : R_DR(FRm) );
728 XOP2IS(OP_ADD, -8, R_R(Rn) );
729 } else {
730 WALIGN32( R_R(Rn) );
731 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
732 XOP2IT(OP_ADD, -4, REG_TMP0 );
733 XOP2TSE(OP_STOREL, REG_TMP0, R_FR(FRm) );
734 XOP2IS(OP_ADD, -4, R_R(Rn) );
735 }
736 :}
737 FMOV @Rm+, FRn {:
738 CHECKFPUEN();
739 if( sh4_xir.double_size ) {
740 RALIGN64( R_R(Rm) );
741 XOP2SSE( OP_LOADQ, R_R(Rm), (FRn&1) ? R_XD(FRn) : R_DR(FRn) );
742 XOP2IS( OP_ADD, 8, R_R(Rm) );
743 } else {
744 RALIGN32( R_R(Rm) );
745 XOP2SSE( OP_LOADL, R_R(Rm), R_FR(FRn) );
746 XOP2IS( OP_ADD, 4, R_R(Rm) );
747 }
748 :}
749 FMOV FRm, @(R0, Rn) {:
750 CHECKFPUEN();
751 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
752 XOP2ST( OP_ADD, R_R(Rn), REG_TMP0 );
753 if( sh4_xir.double_size ) {
754 WALIGN64( REG_TMP0 );
755 XOP2TSE( OP_STOREQ, REG_TMP0, (FRm&1) ? R_XD(FRm) : R_DR(FRm) );
756 } else {
757 WALIGN32( REG_TMP0 );
758 XOP2TSE( OP_STOREL, REG_TMP0, R_FR(FRm) );
759 }
760 :}
761 FMOV @(R0, Rm), FRn {:
762 CHECKFPUEN();
763 XOP2ST( OP_MOV, R_R0, REG_TMP0 );
764 XOP2ST( OP_ADD, R_R(Rm), REG_TMP0 );
765 if( sh4_xir.double_size ) {
766 RALIGN64( REG_TMP0 );
767 XOP2TSE( OP_LOADQ, REG_TMP0, (FRn&1) ? R_XD(FRn) : R_DR(FRn) );
768 } else {
769 RALIGN32( REG_TMP0 );
770 XOP2TSE( OP_LOADL, REG_TMP0, R_FR(FRn) );
771 }
772 :}
773 FLDI0 FRn {: /* IFF PR=0 */
774 CHECKFPUEN();
775 if( sh4_xir.double_prec == 0 ) {
776 XOP2FS( OP_MOV, 0.0, R_FR(FRn) );
777 }
778 :}
779 FLDI1 FRn {: /* IFF PR=0 */
780 CHECKFPUEN();
781 if( sh4_xir.double_prec == 0 ) {
782 XOP2FS( OP_MOV, 1.0, R_FR(FRn) );
783 }
784 :}
785 FLOAT FPUL, FRn {:
786 CHECKFPUEN();
787 if( sh4_xir.double_prec ) {
788 XOP2SS( OP_ITOD, R_FPUL, R_DR(FRn) );
789 } else {
790 XOP2SS( OP_ITOF, R_FPUL, R_FR(FRn) );
791 }
792 :}
793 FTRC FRm, FPUL {:
794 CHECKFPUEN();
795 if( sh4_xir.double_prec ) {
796 XOP2SS( OP_MOVQ, R_DR(FRm), REG_TMPD0 );
797 XOP2FS( OP_MAXD, (double)0x8000000000000000, REG_TMPD0 );
798 XOP2FS( OP_MIND, (double)0x7FFFFFFFFFFFFFFF, REG_TMPD0 );
799 XOP2SS( OP_DTOI, REG_TMPD0, R_FPUL );
800 } else {
801 XOP2SS( OP_MOV, R_FR(FRm), REG_TMPF0 );
802 XOP2FS( OP_MAXF, (double)0x80000000, REG_TMPF0 );
803 XOP2FS( OP_MINF, (double)0x7FFFFFFF, REG_TMPF0 );
804 XOP2SS( OP_FTOI, REG_TMPF0, R_FPUL );
805 }
806 :}
807 FLDS FRm, FPUL {:
808 CHECKFPUEN();
809 XOP2SS( OP_MOV, R_FR(FRm), R_FPUL );
810 :}
811 FSTS FPUL, FRn {:
812 CHECKFPUEN();
813 XOP2SS( OP_MOV, R_FPUL, R_FR(FRn) );
814 :}
815 FCNVDS FRm, FPUL {:
816 CHECKFPUEN();
817 if( sh4_xir.double_prec && !sh4_xir.double_size ) {
818 XOP2SS( OP_DTOF, R_DR(FRm), R_FPUL );
819 }
820 :}
821 FCNVSD FPUL, FRn {:
822 CHECKFPUEN();
823 if( sh4_xir.double_prec && !sh4_xir.double_size ) {
824 XOP2SS( OP_FTOD, R_FPUL, R_DR(FRn) );
825 }
826 :}
827 FABS FRn {:
828 CHECKFPUEN();
829 if( sh4_xir.double_prec ) {
830 XOP2SS( OP_ABSD, R_DR(FRn), R_DR(FRn) );
831 } else {
832 XOP2SS( OP_ABSF, R_FR(FRn), R_FR(FRn) );
833 }
834 :}
835 FADD FRm, FRn {:
836 CHECKFPUEN();
837 if( sh4_xir.double_prec ) {
838 XOP2SS( OP_ADDD, R_DR(FRm), R_DR(FRn) );
839 } else {
840 XOP2SS( OP_ADDF, R_FR(FRm), R_FR(FRn) );
841 }
842 :}
843 FDIV FRm, FRn {:
844 CHECKFPUEN();
845 if( sh4_xir.double_prec ) {
846 XOP2SS( OP_DIVD, R_DR(FRm), R_DR(FRn) );
847 } else {
848 XOP2SS( OP_DIVF, R_FR(FRm), R_FR(FRn) );
849 }
850 :}
851 FMAC FR0, FRm, FRn {:
852 CHECKFPUEN();
853 if( sh4_xir.double_prec == 0 ) {
854 XOP2ST( OP_MOV, R_FR(0), REG_TMP0 );
855 XOP2ST( OP_MULF, R_FR(FRm), REG_TMP0 );
856 XOP2TS( OP_ADDF, REG_TMP0, R_FR(FRn) );
857 }
858 :}
859 FMUL FRm, FRn {:
860 CHECKFPUEN();
861 if( sh4_xir.double_prec ) {
862 XOP2SS( OP_MULD, R_DR(FRm), R_DR(FRn) );
863 } else {
864 XOP2SS( OP_MULF, R_FR(FRm), R_FR(FRn) );
865 }
866 :}
867 FNEG FRn {:
868 CHECKFPUEN();
869 if( sh4_xir.double_prec ) {
870 XOP2SS( OP_NEGD, R_DR(FRn), R_DR(FRn) );
871 } else {
872 XOP2SS( OP_NEGF, R_FR(FRn), R_FR(FRn) );
873 }
874 :}
875 FSRRA FRn {:
876 CHECKFPUEN();
877 if( sh4_xir.double_prec == 0 ) {
878 XOP2SS( OP_RSQRTF, R_FR(FRn), R_FR(FRn) );
879 }
880 :}
881 FSQRT FRn {:
882 CHECKFPUEN();
883 if( sh4_xir.double_prec ) {
884 XOP2SS( OP_SQRTD, R_DR(FRn), R_DR(FRn) );
885 } else {
886 XOP2SS( OP_SQRTF, R_FR(FRn), R_FR(FRn) );
887 }
888 :}
889 FSUB FRm, FRn {:
890 CHECKFPUEN();
891 if( sh4_xir.double_prec ) {
892 XOP2SS( OP_SUBD, R_DR(FRm), R_DR(FRn) );
893 } else {
894 XOP2SS( OP_SUBF, R_FR(FRm), R_FR(FRn) );
895 }
896 :}
897 FCMP/EQ FRm, FRn {:
898 CHECKFPUEN();
899 if( sh4_xir.double_prec ) {
900 XOP2SS( OP_CMPD, R_DR(FRm), R_DR(FRn) );
901 } else {
902 XOP2SS( OP_CMPF, R_FR(FRm), R_FR(FRn) );
903 }
904 XOP1SCC( OP_ST, CC_EQ, R_T );
905 :}
906 FCMP/GT FRm, FRn {:
907 CHECKFPUEN();
908 if( sh4_xir.double_prec ) {
909 XOP2SS( OP_CMPD, R_DR(FRm), R_DR(FRn) );
910 } else {
911 XOP2SS( OP_CMPF, R_FR(FRm), R_FR(FRn) );
912 }
913 XOP1SCC( OP_ST, CC_SGT, R_T );
914 :}
915 FSCA FPUL, FRn {:
916 CHECKFPUEN();
917 if( sh4_xir.double_prec == 0 ) {
918 XOP2SS( OP_SINCOSF, R_FPUL, R_DR(FRn) );
919 }
920 :}
921 FIPR FVm, FVn {:
922 CHECKFPUEN();
923 if( sh4_xir.double_prec == 0 ) {
924 XOP2SS( OP_DOTPRODV, R_FV(FVm), R_FV(FVn) );
925 }
926 :}
927 FTRV XMTRX, FVn {:
928 CHECKFPUEN();
929 if( sh4_xir.double_prec == 0 ) {
930 XOP2SS( OP_MATMULV, R_XMTRX, R_FV(FVn) );
931 }
932 :}
933 FRCHG {:
934 CHECKFPUEN();
935 XOP2IS( OP_XOR, FPSCR_FR, R_FPSCR );
936 XOPCALL0( sh4_switch_fr_banks );
937 :}
938 FSCHG {:
939 CHECKFPUEN();
940 XOP2IS( OP_XOR, FPSCR_SZ, R_FPSCR );
941 XOP2IS( OP_XOR, FPSCR_SZ, R_SH4_MODE );
942 sh4_xir.double_size = !sh4_xir.double_size;
943 :}
944 LDC Rm, SR {:
945 if( in_delay_slot ) {
946 SLOTILLEGAL();
947 } else {
948 CHECKPRIV();
949 XOPCALL1S( sh4_write_sr, R_R(Rm) );
950 }
951 return 2;
952 :}
953 LDC Rm, GBR {: XOP2SS( OP_MOV, R_R(Rm), R_GBR ); :}
954 LDC Rm, VBR {: CHECKPRIV(); XOP2SS( OP_MOV, R_R(Rm), R_VBR ); :}
955 LDC Rm, SSR {: CHECKPRIV(); XOP2SS( OP_MOV, R_R(Rm), R_SSR ); :}
956 LDC Rm, SGR {: CHECKPRIV(); XOP2SS( OP_MOV, R_R(Rm), R_SGR ); :}
957 LDC Rm, SPC {: CHECKPRIV(); XOP2SS( OP_MOV, R_R(Rm), R_SPC ); :}
958 LDC Rm, DBR {: CHECKPRIV(); XOP2SS( OP_MOV, R_R(Rm), R_DBR ); :}
959 LDC Rm, Rn_BANK {: CHECKPRIV(); XOP2SS( OP_MOV, R_R(Rm), R_BANK(Rn_BANK) ); :}
960 LDC.L @Rm+, GBR {:
961 XOP2SSE( OP_LOADL, R_R(Rm), R_GBR );
962 XOP2IS( OP_ADD, 4, R_R(Rm) );
963 :}
964 LDC.L @Rm+, SR {:
965 if( in_delay_slot ) {
966 SLOTILLEGAL();
967 } else {
968 CHECKPRIV();
969 RALIGN32( R_R(Rm) );
970 XOP2STE( OP_LOADL, R_R(Rm), REG_TMP0 );
971 XOP2IS( OP_ADD, 4, R_R(Rm) );
972 XOPCALL1T( sh4_write_sr, REG_TMP0 );
973 }
974 return 2;
975 :}
976 LDC.L @Rm+, VBR {:
977 CHECKPRIV();
978 RALIGN32( R_R(Rm) );
979 XOP2SSE( OP_LOADL, R_R(Rm), R_VBR );
980 XOP2IS( OP_ADD, 4, R_R(Rm) );
981 :}
982 LDC.L @Rm+, SSR {:
983 CHECKPRIV();
984 RALIGN32( R_R(Rm) );
985 XOP2SSE( OP_LOADL, R_R(Rm), R_SSR );
986 XOP2IS( OP_ADD, 4, R_R(Rm) );
987 :}
988 LDC.L @Rm+, SGR {:
989 CHECKPRIV();
990 RALIGN32( R_R(Rm) );
991 XOP2SSE( OP_LOADL, R_R(Rm), R_SGR );
992 XOP2IS( OP_ADD, 4, R_R(Rm) );
993 :}
994 LDC.L @Rm+, SPC {:
995 CHECKPRIV();
996 RALIGN32( R_R(Rm) );
997 XOP2SSE( OP_LOADL, R_R(Rm), R_SPC );
998 XOP2IS( OP_ADD, 4, R_R(Rm) );
999 :}
1000 LDC.L @Rm+, DBR {:
1001 CHECKPRIV();
1002 RALIGN32( R_R(Rm) );
1003 XOP2SSE( OP_LOADL, R_R(Rm), R_DBR );
1004 XOP2IS( OP_ADD, 4, R_R(Rm) );
1005 :}
1006 LDC.L @Rm+, Rn_BANK {:
1007 CHECKPRIV();
1008 RALIGN32( R_R(Rm) );
1009 XOP2SSE( OP_LOADL, R_R(Rm), R_BANK(Rn_BANK) );
1010 XOP2IS( OP_ADD, 4, R_R(Rm) );
1011 :}
1012 LDS Rm, FPSCR {:
1013 CHECKFPUEN();
1014 XOPCALL1S( sh4_write_fpscr, R_R(Rm) );
1015 return 2;
1016 :}
1017 LDS Rm, FPUL {:
1018 CHECKFPUEN();
1019 XOP2SS( OP_MOV, R_R(Rm), R_FPUL );
1020 :}
1021 LDS Rm, MACH {: XOP2SS( OP_MOV, R_R(Rm), R_MACH ); :}
1022 LDS Rm, MACL {: XOP2SS( OP_MOV, R_R(Rm), R_MACL ); :}
1023 LDS Rm, PR {: XOP2SS( OP_MOV, R_R(Rm), R_PR ); :}
1024 LDS.L @Rm+, FPSCR {:
1025 CHECKFPUEN();
1026 RALIGN32( R_R(Rm) );
1027 XOP2STE( OP_LOADL, R_R(Rm), REG_TMP0 );
1028 XOP2IS( OP_ADD, 4, R_R(Rm) );
1029 XOPCALL1T( sh4_write_fpscr, REG_TMP0 );
1030 return 2;
1031 :}
1032 LDS.L @Rm+, FPUL {:
1033 CHECKFPUEN();
1034 RALIGN32( R_R(Rm) );
1035 XOP2SSE( OP_LOADL, R_R(Rm), R_FPUL );
1036 XOP2IS( OP_ADD, 4, R_R(Rm) );
1037 :}
1038 LDS.L @Rm+, MACH {:
1039 RALIGN32( R_R(Rm) );
1040 XOP2SSE( OP_LOADL, R_R(Rm), R_MACH );
1041 XOP2IS( OP_ADD, 4, R_R(Rm) );
1042 :}
1043 LDS.L @Rm+, MACL {:
1044 RALIGN32( R_R(Rm) );
1045 XOP2SSE( OP_LOADL, R_R(Rm), R_MACL );
1046 XOP2IS( OP_ADD, 4, R_R(Rm) );
1047 :}
1048 LDS.L @Rm+, PR {:
1049 RALIGN32( R_R(Rm) );
1050 XOP2SSE( OP_LOADL, R_R(Rm), R_PR );
1051 XOP2IS( OP_ADD, 4, R_R(Rm) );
1052 :}
1053 STC SR, Rn {:
1054 CHECKPRIV();
1055 XOPCALLRS( sh4_read_sr, R_R(Rn) );
1056 :}
1057 STC GBR, Rn {: XOP2SS( OP_MOV, R_GBR, R_R(Rn) ); :}
1058 STC VBR, Rn {: CHECKPRIV(); XOP2SS( OP_MOV, R_VBR, R_R(Rn) ); :}
1059 STC SSR, Rn {: CHECKPRIV(); XOP2SS( OP_MOV, R_SSR, R_R(Rn) ); :}
1060 STC SPC, Rn {: CHECKPRIV(); XOP2SS( OP_MOV, R_SPC, R_R(Rn) ); :}
1061 STC SGR, Rn {: CHECKPRIV(); XOP2SS( OP_MOV, R_SGR, R_R(Rn) ); :}
1062 STC DBR, Rn {: CHECKPRIV(); XOP2SS( OP_MOV, R_DBR, R_R(Rn) ); :}
1063 STC Rm_BANK, Rn {: CHECKPRIV(); XOP2SS( OP_MOV, R_BANK(Rm_BANK), R_R(Rn) ); :}
1064 STC.L SR, @-Rn {:
1065 CHECKPRIV();
1066 XOPCALLRT( sh4_read_sr, REG_TMP1 );
1067 WALIGN32( R_R(Rn) );
1068 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1069 XOP2IT(OP_ADD, -4, REG_TMP0 );
1070 XOP2TTE(OP_STOREL, REG_TMP0, REG_TMP1 );
1071 XOP2IS(OP_ADD, -4, R_R(Rn) );
1072 :}
1073 STC.L VBR, @-Rn {:
1074 CHECKPRIV();
1075 WALIGN32( R_R(Rn) );
1076 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1077 XOP2IT(OP_ADD, -4, REG_TMP0 );
1078 XOP2TSE(OP_STOREL, REG_TMP0, R_VBR );
1079 XOP2IS(OP_ADD, -4, R_R(Rn) );
1080 :}
1081 STC.L SSR, @-Rn {:
1082 CHECKPRIV();
1083 WALIGN32( R_R(Rn) );
1084 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1085 XOP2IT(OP_ADD, -4, REG_TMP0 );
1086 XOP2TSE(OP_STOREL, REG_TMP0, R_SSR );
1087 XOP2IS(OP_ADD, -4, R_R(Rn) );
1088 :}
1089 STC.L SPC, @-Rn {:
1090 CHECKPRIV();
1091 WALIGN32( R_R(Rn) );
1092 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1093 XOP2IT(OP_ADD, -4, REG_TMP0 );
1094 XOP2TSE(OP_STOREL, REG_TMP0, R_SPC );
1095 XOP2IS(OP_ADD, -4, R_R(Rn) );
1096 :}
1097 STC.L SGR, @-Rn {:
1098 CHECKPRIV();
1099 WALIGN32( R_R(Rn) );
1100 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1101 XOP2IT(OP_ADD, -4, REG_TMP0 );
1102 XOP2TSE(OP_STOREL, REG_TMP0, R_SGR );
1103 XOP2IS(OP_ADD, -4, R_R(Rn) );
1104 :}
1105 STC.L DBR, @-Rn {:
1106 CHECKPRIV();
1107 WALIGN32( R_R(Rn) );
1108 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1109 XOP2IT(OP_ADD, -4, REG_TMP0 );
1110 XOP2TSE(OP_STOREL, REG_TMP0, R_DBR );
1111 XOP2IS(OP_ADD, -4, R_R(Rn) );
1112 :}
1113 STC.L Rm_BANK, @-Rn {:
1114 CHECKPRIV();
1115 WALIGN32( R_R(Rn) );
1116 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1117 XOP2IT(OP_ADD, -4, REG_TMP0 );
1118 XOP2TSE(OP_STOREL, REG_TMP0, R_BANK(Rm_BANK) );
1119 XOP2IS(OP_ADD, -4, R_R(Rn) );
1120 :}
1121 STC.L GBR, @-Rn {:
1122 WALIGN32( R_R(Rn) );
1123 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1124 XOP2IT(OP_ADD, -4, REG_TMP0 );
1125 XOP2TSE(OP_STOREL, REG_TMP0, R_GBR );
1126 XOP2IS(OP_ADD, -4, R_R(Rn) );
1127 :}
1128 STS FPSCR, Rn {:
1129 CHECKFPUEN();
1130 XOP2SS( OP_MOV, R_FPSCR, R_R(Rn) );
1131 :}
1132 STS FPUL, Rn {:
1133 CHECKFPUEN();
1134 XOP2SS( OP_MOV, R_FPUL, R_R(Rn) );
1135 :}
1136 STS MACH, Rn {:
1137 XOP2SS( OP_MOV, R_MACH, R_R(Rn) );
1138 :}
1139 STS MACL, Rn {:
1140 XOP2SS( OP_MOV, R_MACL, R_R(Rn) );
1141 :}
1142 STS PR, Rn {:
1143 XOP2SS( OP_MOV, R_PR, R_R(Rn) );
1144 :}
1145 STS.L FPSCR, @-Rn {:
1146 CHECKFPUEN();
1147 WALIGN32( R_R(Rn) );
1148 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1149 XOP2IT(OP_ADD, -4, REG_TMP0 );
1150 XOP2TSE(OP_STOREL, REG_TMP0, R_FPSCR );
1151 XOP2IS(OP_ADD, -4, R_R(Rn) );
1152 :}
1153 STS.L FPUL, @-Rn {:
1154 CHECKFPUEN();
1155 WALIGN32( R_R(Rn) );
1156 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1157 XOP2IT(OP_ADD, -4, REG_TMP0 );
1158 XOP2TSE(OP_STOREL, REG_TMP0, R_FPUL );
1159 XOP2IS(OP_ADD, -4, R_R(Rn) );
1160 :}
1161 STS.L MACH, @-Rn {:
1162 WALIGN32( R_R(Rn) );
1163 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1164 XOP2IT(OP_ADD, -4, REG_TMP0 );
1165 XOP2TSE(OP_STOREL, REG_TMP0, R_MACH );
1166 XOP2IS(OP_ADD, -4, R_R(Rn) );
1167 :}
1168 STS.L MACL, @-Rn {:
1169 WALIGN32( R_R(Rn) );
1170 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1171 XOP2IT(OP_ADD, -4, REG_TMP0 );
1172 XOP2TSE(OP_STOREL, REG_TMP0, R_MACL );
1173 XOP2IS(OP_ADD, -4, R_R(Rn) );
1174 :}
1175 STS.L PR, @-Rn {:
1176 WALIGN32( R_R(Rn) );
1177 XOP2ST( OP_MOV, R_R(Rn), REG_TMP0 );
1178 XOP2IT(OP_ADD, -4, REG_TMP0 );
1179 XOP2TSE(OP_STOREL, REG_TMP0, R_PR );
1180 XOP2IS(OP_ADD, -4, R_R(Rn) );
1181 :}
1183 BF disp {:
1184 if( in_delay_slot ) {
1185 SLOTILLEGAL();
1186 } else {
1187 XOP2IS( OP_ADD, (pc+2 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1188 XOP2IS( OP_CMP, 0, R_T );
1189 XOP2ISCC( OP_ADD, CC_EQ, disp+pc+4-xbb->pc_begin, R_PC );
1190 XOP2ISCC( OP_ADD, CC_NE, pc+2-xbb->pc_begin, R_PC );
1191 XOP0( OP_EXIT );
1192 }
1193 return 2;
1194 :}
1195 BF/S disp {:
1196 if( in_delay_slot ) {
1197 SLOTILLEGAL();
1198 return 2;
1199 } else {
1200 if( UNTRANSLATABLE(pc+2 ) ) {
1201 XOP2IS( OP_ADD, (pc+2 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1202 XOP2SS( OP_MOV, R_PC, R_NEW_PC );
1203 XOP2IS( OP_CMP, 0, R_T );
1204 XOP2ISCC( OP_ADD, CC_EQ, disp+pc+4-xbb->pc_begin, R_NEW_PC );
1205 XOP2ISCC( OP_ADD, CC_NE, pc+4-xbb->pc_begin, R_NEW_PC );
1206 EMU_DELAY_SLOT();
1207 return 2;
1208 } else {
1209 XOP2ST( OP_MOV, R_T, REG_TMP2 );
1210 sh4_decode_instruction( xbb, pc+2, TRUE );
1211 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1212 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1213 XOP2IT( OP_CMP, 0, REG_TMP2 );
1214 XOP2ISCC( OP_ADD, CC_EQ, disp+pc+4-xbb->pc_begin, R_PC );
1215 XOP2ISCC( OP_ADD, CC_NE, pc+4-xbb->pc_begin, R_PC );
1216 XOP0( OP_EXIT );
1217 }
1218 return 4;
1219 }
1220 }
1221 :}
1222 BT disp {:
1223 if( in_delay_slot ) {
1224 SLOTILLEGAL();
1225 } else {
1226 XOP2IS( OP_ADD, (pc+2 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1227 XOP2IS( OP_CMP, 1, R_T );
1228 XOP2ISCC( OP_ADD, CC_EQ, disp+pc+4-xbb->pc_begin, R_PC );
1229 XOP2ISCC( OP_ADD, CC_NE, pc+2-xbb->pc_begin, R_PC );
1230 XOP0( OP_EXIT );
1231 }
1232 return 2;
1233 :}
1234 BT/S disp {:
1235 if( in_delay_slot ) {
1236 SLOTILLEGAL();
1237 return 2;
1238 } else {
1239 if( UNTRANSLATABLE(pc+2 ) ) {
1240 XOP2IS( OP_ADD, (pc+2 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1241 XOP2SS( OP_MOV, R_PC, R_NEW_PC );
1242 XOP2IS( OP_CMP, 1, R_T );
1243 XOP2ISCC( OP_ADD, CC_EQ, disp+pc+4-xbb->pc_begin, R_NEW_PC );
1244 XOP2ISCC( OP_ADD, CC_NE, pc+4-xbb->pc_begin, R_NEW_PC );
1245 EMU_DELAY_SLOT();
1246 return 2;
1247 } else {
1248 XOP2ST( OP_MOV, R_T, REG_TMP2 );
1249 sh4_decode_instruction( xbb, pc+2, TRUE );
1250 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1251 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1252 XOP2IT( OP_CMP, 1, REG_TMP2 );
1253 XOP2ISCC( OP_ADD, CC_EQ, disp+pc+4-xbb->pc_begin, R_PC );
1254 XOP2ISCC( OP_ADD, CC_NE, pc+4-xbb->pc_begin, R_PC );
1255 XOP0( OP_EXIT );
1256 }
1257 return 4;
1258 }
1259 }
1260 :}
1261 BRA disp {:
1262 if( in_delay_slot ) {
1263 SLOTILLEGAL();
1264 return 2;
1265 } else {
1266 if( UNTRANSLATABLE(pc+2) ) {
1267 XOP2SS( OP_MOV, R_PC, R_NEW_PC );
1268 XOP2IS( OP_ADD, pc+disp+4-xbb->pc_begin, R_NEW_PC );
1269 EMU_DELAY_SLOT();
1270 return 2;
1271 } else {
1272 sh4_decode_instruction( xbb, pc+2, TRUE );
1273 if( xbb->ir_ptr->prev == NULL || !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1274 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1275 XOP2IS( OP_ADD, pc+disp+4-xbb->pc_begin, R_PC );
1276 XOP0( OP_EXIT );
1277 }
1278 return 4;
1279 }
1280 }
1281 :}
1282 BRAF Rn {:
1283 if( in_delay_slot ) {
1284 SLOTILLEGAL();
1285 return 2;
1286 } else {
1287 XOP2ST( OP_MOV, R_PC, REG_TMP2 );
1288 XOP2IT( OP_ADD, pc - xbb->pc_begin + 4, REG_TMP2 );
1289 XOP2ST( OP_ADD, R_R(Rn), REG_TMP2 );
1290 if( UNTRANSLATABLE(pc+2) ) {
1291 XOP2TS( OP_MOV, REG_TMP2, R_NEW_PC );
1292 EMU_DELAY_SLOT();
1293 return 2;
1294 } else {
1295 sh4_decode_instruction( xbb, pc + 2, TRUE );
1296 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1297 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1298 XOP2TS( OP_MOV, REG_TMP2, R_PC );
1299 XOP0( OP_EXIT );
1300 }
1301 return 4;
1302 }
1303 }
1304 :}
1305 BSR disp {:
1306 if( in_delay_slot ) {
1307 SLOTILLEGAL();
1308 return 2;
1309 } else {
1310 XOP2SS( OP_MOV, R_PC, R_PR );
1311 XOP2IS( OP_ADD, pc - xbb->pc_begin + 4, R_PR );
1312 if( UNTRANSLATABLE(pc+2) ) {
1313 XOP2SS( OP_MOV, R_PC, R_NEW_PC );
1314 XOP2IS( OP_ADD, pc+disp+4-xbb->pc_begin, R_NEW_PC );
1315 EMU_DELAY_SLOT();
1316 return 2;
1317 } else {
1318 sh4_decode_instruction( xbb, pc+2, TRUE );
1319 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1320 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1321 XOP2IS( OP_ADD, pc+disp+4-xbb->pc_begin, R_PC );
1322 XOP0( OP_EXIT );
1323 }
1324 return 4;
1325 }
1326 }
1327 :}
1328 BSRF Rn {:
1329 if( in_delay_slot ) {
1330 SLOTILLEGAL();
1331 return 2;
1332 } else {
1333 XOP2SS( OP_MOV, R_PC, R_PR );
1334 XOP2IS( OP_ADD, pc - xbb->pc_begin + 4, R_PR );
1335 XOP2ST( OP_MOV, R_R(Rn), REG_TMP2 );
1336 XOP2ST( OP_ADD, R_PC, REG_TMP2 );
1337 XOP2IT( OP_ADD, pc - xbb->pc_begin + 4, REG_TMP2 );
1338 if( UNTRANSLATABLE(pc+2) ) {
1339 XOP2TS( OP_MOV, REG_TMP2, R_NEW_PC );
1340 EMU_DELAY_SLOT();
1341 return 2;
1342 } else {
1343 sh4_decode_instruction( xbb, pc+2, TRUE );
1344 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1345 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1346 XOP2TS( OP_ADD, REG_TMP2, R_PC );
1347 XOP0( OP_EXIT );
1348 }
1349 return 4;
1350 }
1351 }
1352 :}
1353 JMP @Rn {:
1354 if( in_delay_slot ) {
1355 SLOTILLEGAL();
1356 return 2;
1357 } else {
1358 if( UNTRANSLATABLE(pc+2) ) {
1359 XOP2SS( OP_MOV, R_R(Rn), R_NEW_PC );
1360 EMU_DELAY_SLOT();
1361 return 2;
1362 } else {
1363 XOP2ST( OP_MOV, R_R(Rn), REG_TMP2 );
1364 sh4_decode_instruction( xbb, pc+2, TRUE );
1365 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1366 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1367 XOP2TS( OP_MOV, REG_TMP2, R_PC );
1368 XOP0( OP_EXIT );
1369 }
1370 return 4;
1371 }
1372 }
1373 :}
1374 JSR @Rn {:
1375 if( in_delay_slot ) {
1376 SLOTILLEGAL();
1377 return 2;
1378 } else {
1379 XOP2SS( OP_MOV, R_PC, R_PR );
1380 XOP2IS( OP_ADD, pc - xbb->pc_begin + 4, R_PR );
1381 if( UNTRANSLATABLE(pc+2) ) {
1382 XOP2SS( OP_MOV, R_R(Rn), R_NEW_PC );
1383 EMU_DELAY_SLOT();
1384 return 2;
1385 } else {
1386 XOP2ST( OP_MOV, R_R(Rn), REG_TMP2 );
1387 sh4_decode_instruction( xbb, pc+2, TRUE );
1388 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1389 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1390 XOP2TS( OP_MOV, REG_TMP2, R_PC );
1391 XOP0( OP_EXIT );
1392 }
1393 return 4;
1394 }
1395 }
1396 :}
1397 RTE {:
1398 CHECKPRIV();
1399 if( in_delay_slot ) {
1400 SLOTILLEGAL();
1401 return 2;
1402 } else {
1403 if( UNTRANSLATABLE(pc+2) ) {
1404 XOP2SS( OP_MOV, R_SPC, R_NEW_PC );
1405 EMU_DELAY_SLOT();
1406 return 2;
1407 } else {
1408 XOP2ST( OP_MOV, R_SPC, REG_TMP2 );
1409 XOPCALL1S( sh4_write_sr, R_SSR );
1410 sh4_decode_instruction( xbb, pc+2, TRUE );
1411 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1412 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1413 XOP2TS( OP_MOV, REG_TMP2, R_PC );
1414 XOP0( OP_EXIT );
1415 }
1416 return 4;
1417 }
1418 }
1419 :}
1420 RTS {:
1421 if( in_delay_slot ) {
1422 SLOTILLEGAL();
1423 return 2;
1424 } else {
1425 if( UNTRANSLATABLE(pc+2) ) {
1426 XOP2SS( OP_MOV, R_PR, R_NEW_PC );
1427 EMU_DELAY_SLOT();
1428 return 2;
1429 } else {
1430 XOP2ST( OP_MOV, R_PR, REG_TMP2 );
1431 sh4_decode_instruction( xbb, pc+2, TRUE );
1432 if( !XOP_IS_TERMINATOR( xbb->ir_ptr->prev ) ) {
1433 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1434 XOP2TS( OP_MOV, REG_TMP2, R_PC );
1435 XOP0( OP_EXIT );
1436 }
1437 return 4;
1438 }
1439 }
1440 :}
1441 TRAPA #imm {:
1442 XOP2IS( OP_ADD, (pc+4 - xbb->pc_begin) * sh4_cpu_period, R_SLICE_CYCLE );
1443 XOP2IS( OP_ADD, pc+4-xbb->pc_begin, R_PC );
1444 XOPCALL1I( sh4_raise_trap, imm );
1445 XOP0( OP_EXIT );
1446 return 2;
1447 :}
1448 SLEEP {:
1449 XOPCALL0( sh4_sleep );
1450 XOP0( OP_EXIT);
1451 return 2;
1452 :}
1453 UNDEF {: UNDEF(ir); :}
1454 NOP {: /* Do nothing */ :}
1456 %%
1457 return 0;
1458 }
1461 sh4addr_t sh4_decode_basic_block( xir_basic_block_t xbb )
1462 {
1463 sh4addr_t pc;
1465 sh4_xir.fpuen_checked = FALSE;
1466 sh4_xir.double_prec = sh4r.fpscr & FPSCR_PR;
1467 sh4_xir.double_size = sh4r.fpscr & FPSCR_SZ;
1468 xbb->address_space = (sh4r.xlat_sh4_mode&SR_MD) ? sh4_address_space : sh4_user_address_space;
1470 xbb->ir_alloc_begin->prev = NULL;
1471 XOP1I( OP_ENTER, 0 );
1472 for( pc = xbb->pc_begin; pc < xbb->pc_end; pc += 2 ) {
1473 int done = sh4_decode_instruction( xbb, pc, FALSE );
1474 if( done ) {
1475 pc += done;
1476 break;
1477 }
1478 }
1479 xbb->ir_end = xbb->ir_ptr-1;
1480 xbb->ir_end->next = NULL;
1481 xbb->pc_end = pc;
1482 return pc;
1483 }
.