Annotation of qemu/target-xtensa/translate.c, revision 1.1.1.2
1.1 root 1: /*
2: * Xtensa ISA:
3: * http://www.tensilica.com/products/literature-docs/documentation/xtensa-isa-databook.htm
4: *
5: * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions are met:
10: * * Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * * Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * * Neither the name of the Open Source and Linux Lab nor the
16: * names of its contributors may be used to endorse or promote products
17: * derived from this software without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30:
31: #include <stdio.h>
32:
33: #include "cpu.h"
34: #include "exec-all.h"
35: #include "disas.h"
36: #include "tcg-op.h"
37: #include "qemu-log.h"
38: #include "sysemu.h"
39:
1.1.1.2 ! root 40: #include "helper.h"
1.1 root 41: #define GEN_HELPER 1
1.1.1.2 ! root 42: #include "helper.h"
1.1 root 43:
44: typedef struct DisasContext {
45: const XtensaConfig *config;
46: TranslationBlock *tb;
47: uint32_t pc;
48: uint32_t next_pc;
49: int cring;
50: int ring;
51: uint32_t lbeg;
52: uint32_t lend;
53: TCGv_i32 litbase;
54: int is_jmp;
55: int singlestep_enabled;
56:
57: bool sar_5bit;
58: bool sar_m32_5bit;
59: bool sar_m32_allocated;
60: TCGv_i32 sar_m32;
61:
62: uint32_t ccount_delta;
63: unsigned used_window;
1.1.1.2 ! root 64:
! 65: bool debug;
! 66: bool icount;
! 67: TCGv_i32 next_icount;
1.1 root 68: } DisasContext;
69:
70: static TCGv_ptr cpu_env;
71: static TCGv_i32 cpu_pc;
72: static TCGv_i32 cpu_R[16];
73: static TCGv_i32 cpu_SR[256];
74: static TCGv_i32 cpu_UR[256];
75:
76: #include "gen-icount.h"
77:
78: static const char * const sregnames[256] = {
79: [LBEG] = "LBEG",
80: [LEND] = "LEND",
81: [LCOUNT] = "LCOUNT",
82: [SAR] = "SAR",
83: [BR] = "BR",
84: [LITBASE] = "LITBASE",
85: [SCOMPARE1] = "SCOMPARE1",
86: [ACCLO] = "ACCLO",
87: [ACCHI] = "ACCHI",
88: [MR] = "MR0",
89: [MR + 1] = "MR1",
90: [MR + 2] = "MR2",
91: [MR + 3] = "MR3",
92: [WINDOW_BASE] = "WINDOW_BASE",
93: [WINDOW_START] = "WINDOW_START",
94: [PTEVADDR] = "PTEVADDR",
95: [RASID] = "RASID",
96: [ITLBCFG] = "ITLBCFG",
97: [DTLBCFG] = "DTLBCFG",
1.1.1.2 ! root 98: [IBREAKENABLE] = "IBREAKENABLE",
! 99: [IBREAKA] = "IBREAKA0",
! 100: [IBREAKA + 1] = "IBREAKA1",
! 101: [DBREAKA] = "DBREAKA0",
! 102: [DBREAKA + 1] = "DBREAKA1",
! 103: [DBREAKC] = "DBREAKC0",
! 104: [DBREAKC + 1] = "DBREAKC1",
1.1 root 105: [EPC1] = "EPC1",
106: [EPC1 + 1] = "EPC2",
107: [EPC1 + 2] = "EPC3",
108: [EPC1 + 3] = "EPC4",
109: [EPC1 + 4] = "EPC5",
110: [EPC1 + 5] = "EPC6",
111: [EPC1 + 6] = "EPC7",
112: [DEPC] = "DEPC",
113: [EPS2] = "EPS2",
114: [EPS2 + 1] = "EPS3",
115: [EPS2 + 2] = "EPS4",
116: [EPS2 + 3] = "EPS5",
117: [EPS2 + 4] = "EPS6",
118: [EPS2 + 5] = "EPS7",
119: [EXCSAVE1] = "EXCSAVE1",
120: [EXCSAVE1 + 1] = "EXCSAVE2",
121: [EXCSAVE1 + 2] = "EXCSAVE3",
122: [EXCSAVE1 + 3] = "EXCSAVE4",
123: [EXCSAVE1 + 4] = "EXCSAVE5",
124: [EXCSAVE1 + 5] = "EXCSAVE6",
125: [EXCSAVE1 + 6] = "EXCSAVE7",
126: [CPENABLE] = "CPENABLE",
127: [INTSET] = "INTSET",
128: [INTCLEAR] = "INTCLEAR",
129: [INTENABLE] = "INTENABLE",
130: [PS] = "PS",
131: [VECBASE] = "VECBASE",
132: [EXCCAUSE] = "EXCCAUSE",
1.1.1.2 ! root 133: [DEBUGCAUSE] = "DEBUGCAUSE",
1.1 root 134: [CCOUNT] = "CCOUNT",
135: [PRID] = "PRID",
1.1.1.2 ! root 136: [ICOUNT] = "ICOUNT",
! 137: [ICOUNTLEVEL] = "ICOUNTLEVEL",
1.1 root 138: [EXCVADDR] = "EXCVADDR",
139: [CCOMPARE] = "CCOMPARE0",
140: [CCOMPARE + 1] = "CCOMPARE1",
141: [CCOMPARE + 2] = "CCOMPARE2",
142: };
143:
144: static const char * const uregnames[256] = {
145: [THREADPTR] = "THREADPTR",
146: [FCR] = "FCR",
147: [FSR] = "FSR",
148: };
149:
150: void xtensa_translate_init(void)
151: {
152: static const char * const regnames[] = {
153: "ar0", "ar1", "ar2", "ar3",
154: "ar4", "ar5", "ar6", "ar7",
155: "ar8", "ar9", "ar10", "ar11",
156: "ar12", "ar13", "ar14", "ar15",
157: };
158: int i;
159:
160: cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
161: cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.2 ! root 162: offsetof(CPUXtensaState, pc), "pc");
1.1 root 163:
164: for (i = 0; i < 16; i++) {
165: cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.2 ! root 166: offsetof(CPUXtensaState, regs[i]),
1.1 root 167: regnames[i]);
168: }
169:
170: for (i = 0; i < 256; ++i) {
171: if (sregnames[i]) {
172: cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.2 ! root 173: offsetof(CPUXtensaState, sregs[i]),
1.1 root 174: sregnames[i]);
175: }
176: }
177:
178: for (i = 0; i < 256; ++i) {
179: if (uregnames[i]) {
180: cpu_UR[i] = tcg_global_mem_new_i32(TCG_AREG0,
1.1.1.2 ! root 181: offsetof(CPUXtensaState, uregs[i]),
1.1 root 182: uregnames[i]);
183: }
184: }
185: #define GEN_HELPER 2
1.1.1.2 ! root 186: #include "helper.h"
1.1 root 187: }
188:
189: static inline bool option_bits_enabled(DisasContext *dc, uint64_t opt)
190: {
191: return xtensa_option_bits_enabled(dc->config, opt);
192: }
193:
194: static inline bool option_enabled(DisasContext *dc, int opt)
195: {
196: return xtensa_option_enabled(dc->config, opt);
197: }
198:
199: static void init_litbase(DisasContext *dc)
200: {
201: if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
202: dc->litbase = tcg_temp_local_new_i32();
203: tcg_gen_andi_i32(dc->litbase, cpu_SR[LITBASE], 0xfffff000);
204: }
205: }
206:
207: static void reset_litbase(DisasContext *dc)
208: {
209: if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
210: tcg_temp_free(dc->litbase);
211: }
212: }
213:
214: static void init_sar_tracker(DisasContext *dc)
215: {
216: dc->sar_5bit = false;
217: dc->sar_m32_5bit = false;
218: dc->sar_m32_allocated = false;
219: }
220:
221: static void reset_sar_tracker(DisasContext *dc)
222: {
223: if (dc->sar_m32_allocated) {
224: tcg_temp_free(dc->sar_m32);
225: }
226: }
227:
228: static void gen_right_shift_sar(DisasContext *dc, TCGv_i32 sa)
229: {
230: tcg_gen_andi_i32(cpu_SR[SAR], sa, 0x1f);
231: if (dc->sar_m32_5bit) {
232: tcg_gen_discard_i32(dc->sar_m32);
233: }
234: dc->sar_5bit = true;
235: dc->sar_m32_5bit = false;
236: }
237:
238: static void gen_left_shift_sar(DisasContext *dc, TCGv_i32 sa)
239: {
240: TCGv_i32 tmp = tcg_const_i32(32);
241: if (!dc->sar_m32_allocated) {
242: dc->sar_m32 = tcg_temp_local_new_i32();
243: dc->sar_m32_allocated = true;
244: }
245: tcg_gen_andi_i32(dc->sar_m32, sa, 0x1f);
246: tcg_gen_sub_i32(cpu_SR[SAR], tmp, dc->sar_m32);
247: dc->sar_5bit = false;
248: dc->sar_m32_5bit = true;
249: tcg_temp_free(tmp);
250: }
251:
252: static void gen_advance_ccount(DisasContext *dc)
253: {
254: if (dc->ccount_delta > 0) {
255: TCGv_i32 tmp = tcg_const_i32(dc->ccount_delta);
256: dc->ccount_delta = 0;
257: gen_helper_advance_ccount(tmp);
258: tcg_temp_free(tmp);
259: }
260: }
261:
262: static void reset_used_window(DisasContext *dc)
263: {
264: dc->used_window = 0;
265: }
266:
267: static void gen_exception(DisasContext *dc, int excp)
268: {
269: TCGv_i32 tmp = tcg_const_i32(excp);
270: gen_advance_ccount(dc);
271: gen_helper_exception(tmp);
272: tcg_temp_free(tmp);
273: }
274:
275: static void gen_exception_cause(DisasContext *dc, uint32_t cause)
276: {
277: TCGv_i32 tpc = tcg_const_i32(dc->pc);
278: TCGv_i32 tcause = tcg_const_i32(cause);
279: gen_advance_ccount(dc);
280: gen_helper_exception_cause(tpc, tcause);
281: tcg_temp_free(tpc);
282: tcg_temp_free(tcause);
283: if (cause == ILLEGAL_INSTRUCTION_CAUSE ||
284: cause == SYSCALL_CAUSE) {
285: dc->is_jmp = DISAS_UPDATE;
286: }
287: }
288:
289: static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
290: TCGv_i32 vaddr)
291: {
292: TCGv_i32 tpc = tcg_const_i32(dc->pc);
293: TCGv_i32 tcause = tcg_const_i32(cause);
294: gen_advance_ccount(dc);
295: gen_helper_exception_cause_vaddr(tpc, tcause, vaddr);
296: tcg_temp_free(tpc);
297: tcg_temp_free(tcause);
298: }
299:
1.1.1.2 ! root 300: static void gen_debug_exception(DisasContext *dc, uint32_t cause)
! 301: {
! 302: TCGv_i32 tpc = tcg_const_i32(dc->pc);
! 303: TCGv_i32 tcause = tcg_const_i32(cause);
! 304: gen_advance_ccount(dc);
! 305: gen_helper_debug_exception(tpc, tcause);
! 306: tcg_temp_free(tpc);
! 307: tcg_temp_free(tcause);
! 308: if (cause & (DEBUGCAUSE_IB | DEBUGCAUSE_BI | DEBUGCAUSE_BN)) {
! 309: dc->is_jmp = DISAS_UPDATE;
! 310: }
! 311: }
! 312:
1.1 root 313: static void gen_check_privilege(DisasContext *dc)
314: {
315: if (dc->cring) {
316: gen_exception_cause(dc, PRIVILEGED_CAUSE);
317: dc->is_jmp = DISAS_UPDATE;
318: }
319: }
320:
321: static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot)
322: {
323: tcg_gen_mov_i32(cpu_pc, dest);
1.1.1.2 ! root 324: gen_advance_ccount(dc);
! 325: if (dc->icount) {
! 326: tcg_gen_mov_i32(cpu_SR[ICOUNT], dc->next_icount);
! 327: }
1.1 root 328: if (dc->singlestep_enabled) {
329: gen_exception(dc, EXCP_DEBUG);
330: } else {
331: if (slot >= 0) {
332: tcg_gen_goto_tb(slot);
333: tcg_gen_exit_tb((tcg_target_long)dc->tb + slot);
334: } else {
335: tcg_gen_exit_tb(0);
336: }
337: }
338: dc->is_jmp = DISAS_UPDATE;
339: }
340:
341: static void gen_jump(DisasContext *dc, TCGv dest)
342: {
343: gen_jump_slot(dc, dest, -1);
344: }
345:
346: static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
347: {
348: TCGv_i32 tmp = tcg_const_i32(dest);
349: if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
350: slot = -1;
351: }
352: gen_jump_slot(dc, tmp, slot);
353: tcg_temp_free(tmp);
354: }
355:
356: static void gen_callw_slot(DisasContext *dc, int callinc, TCGv_i32 dest,
357: int slot)
358: {
359: TCGv_i32 tcallinc = tcg_const_i32(callinc);
360:
361: tcg_gen_deposit_i32(cpu_SR[PS], cpu_SR[PS],
362: tcallinc, PS_CALLINC_SHIFT, PS_CALLINC_LEN);
363: tcg_temp_free(tcallinc);
364: tcg_gen_movi_i32(cpu_R[callinc << 2],
365: (callinc << 30) | (dc->next_pc & 0x3fffffff));
366: gen_jump_slot(dc, dest, slot);
367: }
368:
369: static void gen_callw(DisasContext *dc, int callinc, TCGv_i32 dest)
370: {
371: gen_callw_slot(dc, callinc, dest, -1);
372: }
373:
374: static void gen_callwi(DisasContext *dc, int callinc, uint32_t dest, int slot)
375: {
376: TCGv_i32 tmp = tcg_const_i32(dest);
377: if (((dc->pc ^ dest) & TARGET_PAGE_MASK) != 0) {
378: slot = -1;
379: }
380: gen_callw_slot(dc, callinc, tmp, slot);
381: tcg_temp_free(tmp);
382: }
383:
384: static bool gen_check_loop_end(DisasContext *dc, int slot)
385: {
386: if (option_enabled(dc, XTENSA_OPTION_LOOP) &&
387: !(dc->tb->flags & XTENSA_TBFLAG_EXCM) &&
388: dc->next_pc == dc->lend) {
389: int label = gen_new_label();
390:
1.1.1.2 ! root 391: gen_advance_ccount(dc);
1.1 root 392: tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_SR[LCOUNT], 0, label);
393: tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_SR[LCOUNT], 1);
394: gen_jumpi(dc, dc->lbeg, slot);
395: gen_set_label(label);
396: gen_jumpi(dc, dc->next_pc, -1);
397: return true;
398: }
399: return false;
400: }
401:
402: static void gen_jumpi_check_loop_end(DisasContext *dc, int slot)
403: {
404: if (!gen_check_loop_end(dc, slot)) {
405: gen_jumpi(dc, dc->next_pc, slot);
406: }
407: }
408:
409: static void gen_brcond(DisasContext *dc, TCGCond cond,
410: TCGv_i32 t0, TCGv_i32 t1, uint32_t offset)
411: {
412: int label = gen_new_label();
413:
1.1.1.2 ! root 414: gen_advance_ccount(dc);
1.1 root 415: tcg_gen_brcond_i32(cond, t0, t1, label);
416: gen_jumpi_check_loop_end(dc, 0);
417: gen_set_label(label);
418: gen_jumpi(dc, dc->pc + offset, 1);
419: }
420:
421: static void gen_brcondi(DisasContext *dc, TCGCond cond,
422: TCGv_i32 t0, uint32_t t1, uint32_t offset)
423: {
424: TCGv_i32 tmp = tcg_const_i32(t1);
425: gen_brcond(dc, cond, t0, tmp, offset);
426: tcg_temp_free(tmp);
427: }
428:
429: static void gen_rsr_ccount(DisasContext *dc, TCGv_i32 d, uint32_t sr)
430: {
431: gen_advance_ccount(dc);
432: tcg_gen_mov_i32(d, cpu_SR[sr]);
433: }
434:
435: static void gen_rsr_ptevaddr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
436: {
437: tcg_gen_shri_i32(d, cpu_SR[EXCVADDR], 10);
438: tcg_gen_or_i32(d, d, cpu_SR[sr]);
439: tcg_gen_andi_i32(d, d, 0xfffffffc);
440: }
441:
442: static void gen_rsr(DisasContext *dc, TCGv_i32 d, uint32_t sr)
443: {
444: static void (* const rsr_handler[256])(DisasContext *dc,
445: TCGv_i32 d, uint32_t sr) = {
446: [CCOUNT] = gen_rsr_ccount,
447: [PTEVADDR] = gen_rsr_ptevaddr,
448: };
449:
450: if (sregnames[sr]) {
451: if (rsr_handler[sr]) {
452: rsr_handler[sr](dc, d, sr);
453: } else {
454: tcg_gen_mov_i32(d, cpu_SR[sr]);
455: }
456: } else {
457: qemu_log("RSR %d not implemented, ", sr);
458: }
459: }
460:
461: static void gen_wsr_lbeg(DisasContext *dc, uint32_t sr, TCGv_i32 s)
462: {
463: gen_helper_wsr_lbeg(s);
1.1.1.2 ! root 464: gen_jumpi_check_loop_end(dc, 0);
1.1 root 465: }
466:
467: static void gen_wsr_lend(DisasContext *dc, uint32_t sr, TCGv_i32 s)
468: {
469: gen_helper_wsr_lend(s);
1.1.1.2 ! root 470: gen_jumpi_check_loop_end(dc, 0);
1.1 root 471: }
472:
473: static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
474: {
475: tcg_gen_andi_i32(cpu_SR[sr], s, 0x3f);
476: if (dc->sar_m32_5bit) {
477: tcg_gen_discard_i32(dc->sar_m32);
478: }
479: dc->sar_5bit = false;
480: dc->sar_m32_5bit = false;
481: }
482:
483: static void gen_wsr_br(DisasContext *dc, uint32_t sr, TCGv_i32 s)
484: {
485: tcg_gen_andi_i32(cpu_SR[sr], s, 0xffff);
486: }
487:
488: static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
489: {
490: tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001);
491: /* This can change tb->flags, so exit tb */
492: gen_jumpi_check_loop_end(dc, -1);
493: }
494:
495: static void gen_wsr_acchi(DisasContext *dc, uint32_t sr, TCGv_i32 s)
496: {
497: tcg_gen_ext8s_i32(cpu_SR[sr], s);
498: }
499:
500: static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
501: {
502: gen_helper_wsr_windowbase(v);
503: reset_used_window(dc);
504: }
505:
506: static void gen_wsr_windowstart(DisasContext *dc, uint32_t sr, TCGv_i32 v)
507: {
508: tcg_gen_andi_i32(cpu_SR[sr], v, (1 << dc->config->nareg / 4) - 1);
509: reset_used_window(dc);
510: }
511:
512: static void gen_wsr_ptevaddr(DisasContext *dc, uint32_t sr, TCGv_i32 v)
513: {
514: tcg_gen_andi_i32(cpu_SR[sr], v, 0xffc00000);
515: }
516:
517: static void gen_wsr_rasid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
518: {
519: gen_helper_wsr_rasid(v);
520: /* This can change tb->flags, so exit tb */
521: gen_jumpi_check_loop_end(dc, -1);
522: }
523:
524: static void gen_wsr_tlbcfg(DisasContext *dc, uint32_t sr, TCGv_i32 v)
525: {
526: tcg_gen_andi_i32(cpu_SR[sr], v, 0x01130000);
527: }
528:
1.1.1.2 ! root 529: static void gen_wsr_ibreakenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
! 530: {
! 531: gen_helper_wsr_ibreakenable(v);
! 532: gen_jumpi_check_loop_end(dc, 0);
! 533: }
! 534:
! 535: static void gen_wsr_ibreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
! 536: {
! 537: unsigned id = sr - IBREAKA;
! 538:
! 539: if (id < dc->config->nibreak) {
! 540: TCGv_i32 tmp = tcg_const_i32(id);
! 541: gen_helper_wsr_ibreaka(tmp, v);
! 542: tcg_temp_free(tmp);
! 543: gen_jumpi_check_loop_end(dc, 0);
! 544: }
! 545: }
! 546:
! 547: static void gen_wsr_dbreaka(DisasContext *dc, uint32_t sr, TCGv_i32 v)
! 548: {
! 549: unsigned id = sr - DBREAKA;
! 550:
! 551: if (id < dc->config->ndbreak) {
! 552: TCGv_i32 tmp = tcg_const_i32(id);
! 553: gen_helper_wsr_dbreaka(tmp, v);
! 554: tcg_temp_free(tmp);
! 555: }
! 556: }
! 557:
! 558: static void gen_wsr_dbreakc(DisasContext *dc, uint32_t sr, TCGv_i32 v)
! 559: {
! 560: unsigned id = sr - DBREAKC;
! 561:
! 562: if (id < dc->config->ndbreak) {
! 563: TCGv_i32 tmp = tcg_const_i32(id);
! 564: gen_helper_wsr_dbreakc(tmp, v);
! 565: tcg_temp_free(tmp);
! 566: }
! 567: }
! 568:
1.1 root 569: static void gen_wsr_intset(DisasContext *dc, uint32_t sr, TCGv_i32 v)
570: {
571: tcg_gen_andi_i32(cpu_SR[sr], v,
572: dc->config->inttype_mask[INTTYPE_SOFTWARE]);
573: gen_helper_check_interrupts(cpu_env);
574: gen_jumpi_check_loop_end(dc, 0);
575: }
576:
577: static void gen_wsr_intclear(DisasContext *dc, uint32_t sr, TCGv_i32 v)
578: {
579: TCGv_i32 tmp = tcg_temp_new_i32();
580:
581: tcg_gen_andi_i32(tmp, v,
582: dc->config->inttype_mask[INTTYPE_EDGE] |
583: dc->config->inttype_mask[INTTYPE_NMI] |
584: dc->config->inttype_mask[INTTYPE_SOFTWARE]);
585: tcg_gen_andc_i32(cpu_SR[INTSET], cpu_SR[INTSET], tmp);
586: tcg_temp_free(tmp);
587: gen_helper_check_interrupts(cpu_env);
588: }
589:
590: static void gen_wsr_intenable(DisasContext *dc, uint32_t sr, TCGv_i32 v)
591: {
592: tcg_gen_mov_i32(cpu_SR[sr], v);
593: gen_helper_check_interrupts(cpu_env);
594: gen_jumpi_check_loop_end(dc, 0);
595: }
596:
597: static void gen_wsr_ps(DisasContext *dc, uint32_t sr, TCGv_i32 v)
598: {
599: uint32_t mask = PS_WOE | PS_CALLINC | PS_OWB |
600: PS_UM | PS_EXCM | PS_INTLEVEL;
601:
602: if (option_enabled(dc, XTENSA_OPTION_MMU)) {
603: mask |= PS_RING;
604: }
605: tcg_gen_andi_i32(cpu_SR[sr], v, mask);
606: reset_used_window(dc);
607: gen_helper_check_interrupts(cpu_env);
608: /* This can change mmu index and tb->flags, so exit tb */
609: gen_jumpi_check_loop_end(dc, -1);
610: }
611:
1.1.1.2 ! root 612: static void gen_wsr_debugcause(DisasContext *dc, uint32_t sr, TCGv_i32 v)
! 613: {
! 614: }
! 615:
1.1 root 616: static void gen_wsr_prid(DisasContext *dc, uint32_t sr, TCGv_i32 v)
617: {
618: }
619:
1.1.1.2 ! root 620: static void gen_wsr_icount(DisasContext *dc, uint32_t sr, TCGv_i32 v)
! 621: {
! 622: if (dc->icount) {
! 623: tcg_gen_mov_i32(dc->next_icount, v);
! 624: } else {
! 625: tcg_gen_mov_i32(cpu_SR[sr], v);
! 626: }
! 627: }
! 628:
! 629: static void gen_wsr_icountlevel(DisasContext *dc, uint32_t sr, TCGv_i32 v)
! 630: {
! 631: tcg_gen_andi_i32(cpu_SR[sr], v, 0xf);
! 632: /* This can change tb->flags, so exit tb */
! 633: gen_jumpi_check_loop_end(dc, -1);
! 634: }
! 635:
1.1 root 636: static void gen_wsr_ccompare(DisasContext *dc, uint32_t sr, TCGv_i32 v)
637: {
638: uint32_t id = sr - CCOMPARE;
639: if (id < dc->config->nccompare) {
640: uint32_t int_bit = 1 << dc->config->timerint[id];
641: gen_advance_ccount(dc);
642: tcg_gen_mov_i32(cpu_SR[sr], v);
643: tcg_gen_andi_i32(cpu_SR[INTSET], cpu_SR[INTSET], ~int_bit);
644: gen_helper_check_interrupts(cpu_env);
645: }
646: }
647:
648: static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
649: {
650: static void (* const wsr_handler[256])(DisasContext *dc,
651: uint32_t sr, TCGv_i32 v) = {
652: [LBEG] = gen_wsr_lbeg,
653: [LEND] = gen_wsr_lend,
654: [SAR] = gen_wsr_sar,
655: [BR] = gen_wsr_br,
656: [LITBASE] = gen_wsr_litbase,
657: [ACCHI] = gen_wsr_acchi,
658: [WINDOW_BASE] = gen_wsr_windowbase,
659: [WINDOW_START] = gen_wsr_windowstart,
660: [PTEVADDR] = gen_wsr_ptevaddr,
661: [RASID] = gen_wsr_rasid,
662: [ITLBCFG] = gen_wsr_tlbcfg,
663: [DTLBCFG] = gen_wsr_tlbcfg,
1.1.1.2 ! root 664: [IBREAKENABLE] = gen_wsr_ibreakenable,
! 665: [IBREAKA] = gen_wsr_ibreaka,
! 666: [IBREAKA + 1] = gen_wsr_ibreaka,
! 667: [DBREAKA] = gen_wsr_dbreaka,
! 668: [DBREAKA + 1] = gen_wsr_dbreaka,
! 669: [DBREAKC] = gen_wsr_dbreakc,
! 670: [DBREAKC + 1] = gen_wsr_dbreakc,
1.1 root 671: [INTSET] = gen_wsr_intset,
672: [INTCLEAR] = gen_wsr_intclear,
673: [INTENABLE] = gen_wsr_intenable,
674: [PS] = gen_wsr_ps,
1.1.1.2 ! root 675: [DEBUGCAUSE] = gen_wsr_debugcause,
1.1 root 676: [PRID] = gen_wsr_prid,
1.1.1.2 ! root 677: [ICOUNT] = gen_wsr_icount,
! 678: [ICOUNTLEVEL] = gen_wsr_icountlevel,
1.1 root 679: [CCOMPARE] = gen_wsr_ccompare,
680: [CCOMPARE + 1] = gen_wsr_ccompare,
681: [CCOMPARE + 2] = gen_wsr_ccompare,
682: };
683:
684: if (sregnames[sr]) {
685: if (wsr_handler[sr]) {
686: wsr_handler[sr](dc, sr, s);
687: } else {
688: tcg_gen_mov_i32(cpu_SR[sr], s);
689: }
690: } else {
691: qemu_log("WSR %d not implemented, ", sr);
692: }
693: }
694:
695: static void gen_load_store_alignment(DisasContext *dc, int shift,
696: TCGv_i32 addr, bool no_hw_alignment)
697: {
698: if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
699: tcg_gen_andi_i32(addr, addr, ~0 << shift);
700: } else if (option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT) &&
701: no_hw_alignment) {
702: int label = gen_new_label();
703: TCGv_i32 tmp = tcg_temp_new_i32();
704: tcg_gen_andi_i32(tmp, addr, ~(~0 << shift));
705: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
706: gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
707: gen_set_label(label);
708: tcg_temp_free(tmp);
709: }
710: }
711:
712: static void gen_waiti(DisasContext *dc, uint32_t imm4)
713: {
714: TCGv_i32 pc = tcg_const_i32(dc->next_pc);
715: TCGv_i32 intlevel = tcg_const_i32(imm4);
716: gen_advance_ccount(dc);
717: gen_helper_waiti(pc, intlevel);
718: tcg_temp_free(pc);
719: tcg_temp_free(intlevel);
720: }
721:
722: static void gen_window_check1(DisasContext *dc, unsigned r1)
723: {
724: if (dc->tb->flags & XTENSA_TBFLAG_EXCM) {
725: return;
726: }
727: if (option_enabled(dc, XTENSA_OPTION_WINDOWED_REGISTER) &&
728: r1 / 4 > dc->used_window) {
729: TCGv_i32 pc = tcg_const_i32(dc->pc);
730: TCGv_i32 w = tcg_const_i32(r1 / 4);
731:
732: dc->used_window = r1 / 4;
733: gen_advance_ccount(dc);
734: gen_helper_window_check(pc, w);
735:
736: tcg_temp_free(w);
737: tcg_temp_free(pc);
738: }
739: }
740:
741: static void gen_window_check2(DisasContext *dc, unsigned r1, unsigned r2)
742: {
743: gen_window_check1(dc, r1 > r2 ? r1 : r2);
744: }
745:
746: static void gen_window_check3(DisasContext *dc, unsigned r1, unsigned r2,
747: unsigned r3)
748: {
749: gen_window_check2(dc, r1, r2 > r3 ? r2 : r3);
750: }
751:
752: static TCGv_i32 gen_mac16_m(TCGv_i32 v, bool hi, bool is_unsigned)
753: {
754: TCGv_i32 m = tcg_temp_new_i32();
755:
756: if (hi) {
757: (is_unsigned ? tcg_gen_shri_i32 : tcg_gen_sari_i32)(m, v, 16);
758: } else {
759: (is_unsigned ? tcg_gen_ext16u_i32 : tcg_gen_ext16s_i32)(m, v);
760: }
761: return m;
762: }
763:
764: static void disas_xtensa_insn(DisasContext *dc)
765: {
766: #define HAS_OPTION_BITS(opt) do { \
767: if (!option_bits_enabled(dc, opt)) { \
768: qemu_log("Option is not enabled %s:%d\n", \
769: __FILE__, __LINE__); \
770: goto invalid_opcode; \
771: } \
772: } while (0)
773:
774: #define HAS_OPTION(opt) HAS_OPTION_BITS(XTENSA_OPTION_BIT(opt))
775:
776: #define TBD() qemu_log("TBD(pc = %08x): %s:%d\n", dc->pc, __FILE__, __LINE__)
777: #define RESERVED() do { \
778: qemu_log("RESERVED(pc = %08x, %02x%02x%02x): %s:%d\n", \
779: dc->pc, b0, b1, b2, __FILE__, __LINE__); \
780: goto invalid_opcode; \
781: } while (0)
782:
783:
784: #ifdef TARGET_WORDS_BIGENDIAN
785: #define OP0 (((b0) & 0xf0) >> 4)
786: #define OP1 (((b2) & 0xf0) >> 4)
787: #define OP2 ((b2) & 0xf)
788: #define RRR_R ((b1) & 0xf)
789: #define RRR_S (((b1) & 0xf0) >> 4)
790: #define RRR_T ((b0) & 0xf)
791: #else
792: #define OP0 (((b0) & 0xf))
793: #define OP1 (((b2) & 0xf))
794: #define OP2 (((b2) & 0xf0) >> 4)
795: #define RRR_R (((b1) & 0xf0) >> 4)
796: #define RRR_S (((b1) & 0xf))
797: #define RRR_T (((b0) & 0xf0) >> 4)
798: #endif
799: #define RRR_X ((RRR_R & 0x4) >> 2)
800: #define RRR_Y ((RRR_T & 0x4) >> 2)
801: #define RRR_W (RRR_R & 0x3)
802:
803: #define RRRN_R RRR_R
804: #define RRRN_S RRR_S
805: #define RRRN_T RRR_T
806:
807: #define RRI8_R RRR_R
808: #define RRI8_S RRR_S
809: #define RRI8_T RRR_T
810: #define RRI8_IMM8 (b2)
811: #define RRI8_IMM8_SE ((((b2) & 0x80) ? 0xffffff00 : 0) | RRI8_IMM8)
812:
813: #ifdef TARGET_WORDS_BIGENDIAN
814: #define RI16_IMM16 (((b1) << 8) | (b2))
815: #else
816: #define RI16_IMM16 (((b2) << 8) | (b1))
817: #endif
818:
819: #ifdef TARGET_WORDS_BIGENDIAN
820: #define CALL_N (((b0) & 0xc) >> 2)
821: #define CALL_OFFSET ((((b0) & 0x3) << 16) | ((b1) << 8) | (b2))
822: #else
823: #define CALL_N (((b0) & 0x30) >> 4)
824: #define CALL_OFFSET ((((b0) & 0xc0) >> 6) | ((b1) << 2) | ((b2) << 10))
825: #endif
826: #define CALL_OFFSET_SE \
827: (((CALL_OFFSET & 0x20000) ? 0xfffc0000 : 0) | CALL_OFFSET)
828:
829: #define CALLX_N CALL_N
830: #ifdef TARGET_WORDS_BIGENDIAN
831: #define CALLX_M ((b0) & 0x3)
832: #else
833: #define CALLX_M (((b0) & 0xc0) >> 6)
834: #endif
835: #define CALLX_S RRR_S
836:
837: #define BRI12_M CALLX_M
838: #define BRI12_S RRR_S
839: #ifdef TARGET_WORDS_BIGENDIAN
840: #define BRI12_IMM12 ((((b1) & 0xf) << 8) | (b2))
841: #else
842: #define BRI12_IMM12 ((((b1) & 0xf0) >> 4) | ((b2) << 4))
843: #endif
844: #define BRI12_IMM12_SE (((BRI12_IMM12 & 0x800) ? 0xfffff000 : 0) | BRI12_IMM12)
845:
846: #define BRI8_M BRI12_M
847: #define BRI8_R RRI8_R
848: #define BRI8_S RRI8_S
849: #define BRI8_IMM8 RRI8_IMM8
850: #define BRI8_IMM8_SE RRI8_IMM8_SE
851:
852: #define RSR_SR (b1)
853:
854: uint8_t b0 = ldub_code(dc->pc);
855: uint8_t b1 = ldub_code(dc->pc + 1);
1.1.1.2 ! root 856: uint8_t b2 = 0;
1.1 root 857:
858: static const uint32_t B4CONST[] = {
859: 0xffffffff, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
860: };
861:
862: static const uint32_t B4CONSTU[] = {
863: 32768, 65536, 2, 3, 4, 5, 6, 7, 8, 10, 12, 16, 32, 64, 128, 256
864: };
865:
866: if (OP0 >= 8) {
867: dc->next_pc = dc->pc + 2;
868: HAS_OPTION(XTENSA_OPTION_CODE_DENSITY);
869: } else {
870: dc->next_pc = dc->pc + 3;
1.1.1.2 ! root 871: b2 = ldub_code(dc->pc + 2);
1.1 root 872: }
873:
874: switch (OP0) {
875: case 0: /*QRST*/
876: switch (OP1) {
877: case 0: /*RST0*/
878: switch (OP2) {
879: case 0: /*ST0*/
880: if ((RRR_R & 0xc) == 0x8) {
881: HAS_OPTION(XTENSA_OPTION_BOOLEAN);
882: }
883:
884: switch (RRR_R) {
885: case 0: /*SNM0*/
886: switch (CALLX_M) {
887: case 0: /*ILL*/
888: gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
889: break;
890:
891: case 1: /*reserved*/
892: RESERVED();
893: break;
894:
895: case 2: /*JR*/
896: switch (CALLX_N) {
897: case 0: /*RET*/
898: case 2: /*JX*/
899: gen_window_check1(dc, CALLX_S);
900: gen_jump(dc, cpu_R[CALLX_S]);
901: break;
902:
903: case 1: /*RETWw*/
904: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
905: {
906: TCGv_i32 tmp = tcg_const_i32(dc->pc);
907: gen_advance_ccount(dc);
908: gen_helper_retw(tmp, tmp);
909: gen_jump(dc, tmp);
910: tcg_temp_free(tmp);
911: }
912: break;
913:
914: case 3: /*reserved*/
915: RESERVED();
916: break;
917: }
918: break;
919:
920: case 3: /*CALLX*/
921: gen_window_check2(dc, CALLX_S, CALLX_N << 2);
922: switch (CALLX_N) {
923: case 0: /*CALLX0*/
924: {
925: TCGv_i32 tmp = tcg_temp_new_i32();
926: tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
927: tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
928: gen_jump(dc, tmp);
929: tcg_temp_free(tmp);
930: }
931: break;
932:
933: case 1: /*CALLX4w*/
934: case 2: /*CALLX8w*/
935: case 3: /*CALLX12w*/
936: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
937: {
938: TCGv_i32 tmp = tcg_temp_new_i32();
939:
940: tcg_gen_mov_i32(tmp, cpu_R[CALLX_S]);
941: gen_callw(dc, CALLX_N, tmp);
942: tcg_temp_free(tmp);
943: }
944: break;
945: }
946: break;
947: }
948: break;
949:
950: case 1: /*MOVSPw*/
951: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
952: gen_window_check2(dc, RRR_T, RRR_S);
953: {
954: TCGv_i32 pc = tcg_const_i32(dc->pc);
955: gen_advance_ccount(dc);
956: gen_helper_movsp(pc);
957: tcg_gen_mov_i32(cpu_R[RRR_T], cpu_R[RRR_S]);
958: tcg_temp_free(pc);
959: }
960: break;
961:
962: case 2: /*SYNC*/
963: switch (RRR_T) {
964: case 0: /*ISYNC*/
965: break;
966:
967: case 1: /*RSYNC*/
968: break;
969:
970: case 2: /*ESYNC*/
971: break;
972:
973: case 3: /*DSYNC*/
974: break;
975:
976: case 8: /*EXCW*/
977: HAS_OPTION(XTENSA_OPTION_EXCEPTION);
978: break;
979:
980: case 12: /*MEMW*/
981: break;
982:
983: case 13: /*EXTW*/
984: break;
985:
986: case 15: /*NOP*/
987: break;
988:
989: default: /*reserved*/
990: RESERVED();
991: break;
992: }
993: break;
994:
995: case 3: /*RFEIx*/
996: switch (RRR_T) {
997: case 0: /*RFETx*/
998: HAS_OPTION(XTENSA_OPTION_EXCEPTION);
999: switch (RRR_S) {
1000: case 0: /*RFEx*/
1001: gen_check_privilege(dc);
1002: tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
1003: gen_helper_check_interrupts(cpu_env);
1004: gen_jump(dc, cpu_SR[EPC1]);
1005: break;
1006:
1007: case 1: /*RFUEx*/
1008: RESERVED();
1009: break;
1010:
1011: case 2: /*RFDEx*/
1012: gen_check_privilege(dc);
1013: gen_jump(dc, cpu_SR[
1014: dc->config->ndepc ? DEPC : EPC1]);
1015: break;
1016:
1017: case 4: /*RFWOw*/
1018: case 5: /*RFWUw*/
1019: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
1020: gen_check_privilege(dc);
1021: {
1022: TCGv_i32 tmp = tcg_const_i32(1);
1023:
1024: tcg_gen_andi_i32(
1025: cpu_SR[PS], cpu_SR[PS], ~PS_EXCM);
1026: tcg_gen_shl_i32(tmp, tmp, cpu_SR[WINDOW_BASE]);
1027:
1028: if (RRR_S == 4) {
1029: tcg_gen_andc_i32(cpu_SR[WINDOW_START],
1030: cpu_SR[WINDOW_START], tmp);
1031: } else {
1032: tcg_gen_or_i32(cpu_SR[WINDOW_START],
1033: cpu_SR[WINDOW_START], tmp);
1034: }
1035:
1036: gen_helper_restore_owb();
1037: gen_helper_check_interrupts(cpu_env);
1038: gen_jump(dc, cpu_SR[EPC1]);
1039:
1040: tcg_temp_free(tmp);
1041: }
1042: break;
1043:
1044: default: /*reserved*/
1045: RESERVED();
1046: break;
1047: }
1048: break;
1049:
1050: case 1: /*RFIx*/
1051: HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT);
1052: if (RRR_S >= 2 && RRR_S <= dc->config->nlevel) {
1053: gen_check_privilege(dc);
1054: tcg_gen_mov_i32(cpu_SR[PS],
1055: cpu_SR[EPS2 + RRR_S - 2]);
1056: gen_helper_check_interrupts(cpu_env);
1057: gen_jump(dc, cpu_SR[EPC1 + RRR_S - 1]);
1058: } else {
1059: qemu_log("RFI %d is illegal\n", RRR_S);
1060: gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
1061: }
1062: break;
1063:
1064: case 2: /*RFME*/
1065: TBD();
1066: break;
1067:
1068: default: /*reserved*/
1069: RESERVED();
1070: break;
1071:
1072: }
1073: break;
1074:
1075: case 4: /*BREAKx*/
1.1.1.2 ! root 1076: HAS_OPTION(XTENSA_OPTION_DEBUG);
! 1077: if (dc->debug) {
! 1078: gen_debug_exception(dc, DEBUGCAUSE_BI);
! 1079: }
1.1 root 1080: break;
1081:
1082: case 5: /*SYSCALLx*/
1083: HAS_OPTION(XTENSA_OPTION_EXCEPTION);
1084: switch (RRR_S) {
1085: case 0: /*SYSCALLx*/
1086: gen_exception_cause(dc, SYSCALL_CAUSE);
1087: break;
1088:
1089: case 1: /*SIMCALL*/
1090: if (semihosting_enabled) {
1091: gen_check_privilege(dc);
1092: gen_helper_simcall(cpu_env);
1093: } else {
1094: qemu_log("SIMCALL but semihosting is disabled\n");
1095: gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
1096: }
1097: break;
1098:
1099: default:
1100: RESERVED();
1101: break;
1102: }
1103: break;
1104:
1105: case 6: /*RSILx*/
1106: HAS_OPTION(XTENSA_OPTION_INTERRUPT);
1107: gen_check_privilege(dc);
1108: gen_window_check1(dc, RRR_T);
1109: tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]);
1110: tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_INTLEVEL);
1111: tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S);
1112: gen_helper_check_interrupts(cpu_env);
1113: gen_jumpi_check_loop_end(dc, 0);
1114: break;
1115:
1116: case 7: /*WAITIx*/
1117: HAS_OPTION(XTENSA_OPTION_INTERRUPT);
1118: gen_check_privilege(dc);
1119: gen_waiti(dc, RRR_S);
1120: break;
1121:
1122: case 8: /*ANY4p*/
1123: case 9: /*ALL4p*/
1124: case 10: /*ANY8p*/
1125: case 11: /*ALL8p*/
1126: HAS_OPTION(XTENSA_OPTION_BOOLEAN);
1127: {
1128: const unsigned shift = (RRR_R & 2) ? 8 : 4;
1129: TCGv_i32 mask = tcg_const_i32(
1130: ((1 << shift) - 1) << RRR_S);
1131: TCGv_i32 tmp = tcg_temp_new_i32();
1132:
1133: tcg_gen_and_i32(tmp, cpu_SR[BR], mask);
1134: if (RRR_R & 1) { /*ALL*/
1135: tcg_gen_addi_i32(tmp, tmp, 1 << RRR_S);
1136: } else { /*ANY*/
1137: tcg_gen_add_i32(tmp, tmp, mask);
1138: }
1139: tcg_gen_shri_i32(tmp, tmp, RRR_S + shift);
1140: tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR],
1141: tmp, RRR_T, 1);
1142: tcg_temp_free(mask);
1143: tcg_temp_free(tmp);
1144: }
1145: break;
1146:
1147: default: /*reserved*/
1148: RESERVED();
1149: break;
1150:
1151: }
1152: break;
1153:
1154: case 1: /*AND*/
1155: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1156: tcg_gen_and_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1157: break;
1158:
1159: case 2: /*OR*/
1160: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1161: tcg_gen_or_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1162: break;
1163:
1164: case 3: /*XOR*/
1165: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1166: tcg_gen_xor_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1167: break;
1168:
1169: case 4: /*ST1*/
1170: switch (RRR_R) {
1171: case 0: /*SSR*/
1172: gen_window_check1(dc, RRR_S);
1173: gen_right_shift_sar(dc, cpu_R[RRR_S]);
1174: break;
1175:
1176: case 1: /*SSL*/
1177: gen_window_check1(dc, RRR_S);
1178: gen_left_shift_sar(dc, cpu_R[RRR_S]);
1179: break;
1180:
1181: case 2: /*SSA8L*/
1182: gen_window_check1(dc, RRR_S);
1183: {
1184: TCGv_i32 tmp = tcg_temp_new_i32();
1185: tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
1186: gen_right_shift_sar(dc, tmp);
1187: tcg_temp_free(tmp);
1188: }
1189: break;
1190:
1191: case 3: /*SSA8B*/
1192: gen_window_check1(dc, RRR_S);
1193: {
1194: TCGv_i32 tmp = tcg_temp_new_i32();
1195: tcg_gen_shli_i32(tmp, cpu_R[RRR_S], 3);
1196: gen_left_shift_sar(dc, tmp);
1197: tcg_temp_free(tmp);
1198: }
1199: break;
1200:
1201: case 4: /*SSAI*/
1202: {
1203: TCGv_i32 tmp = tcg_const_i32(
1204: RRR_S | ((RRR_T & 1) << 4));
1205: gen_right_shift_sar(dc, tmp);
1206: tcg_temp_free(tmp);
1207: }
1208: break;
1209:
1210: case 6: /*RER*/
1211: TBD();
1212: break;
1213:
1214: case 7: /*WER*/
1215: TBD();
1216: break;
1217:
1218: case 8: /*ROTWw*/
1219: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
1220: gen_check_privilege(dc);
1221: {
1222: TCGv_i32 tmp = tcg_const_i32(
1223: RRR_T | ((RRR_T & 8) ? 0xfffffff0 : 0));
1224: gen_helper_rotw(tmp);
1225: tcg_temp_free(tmp);
1226: reset_used_window(dc);
1227: }
1228: break;
1229:
1230: case 14: /*NSAu*/
1231: HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);
1232: gen_window_check2(dc, RRR_S, RRR_T);
1233: gen_helper_nsa(cpu_R[RRR_T], cpu_R[RRR_S]);
1234: break;
1235:
1236: case 15: /*NSAUu*/
1237: HAS_OPTION(XTENSA_OPTION_MISC_OP_NSA);
1238: gen_window_check2(dc, RRR_S, RRR_T);
1239: gen_helper_nsau(cpu_R[RRR_T], cpu_R[RRR_S]);
1240: break;
1241:
1242: default: /*reserved*/
1243: RESERVED();
1244: break;
1245: }
1246: break;
1247:
1248: case 5: /*TLB*/
1249: HAS_OPTION_BITS(
1250: XTENSA_OPTION_BIT(XTENSA_OPTION_MMU) |
1251: XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) |
1252: XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION));
1253: gen_check_privilege(dc);
1254: gen_window_check2(dc, RRR_S, RRR_T);
1255: {
1256: TCGv_i32 dtlb = tcg_const_i32((RRR_R & 8) != 0);
1257:
1258: switch (RRR_R & 7) {
1259: case 3: /*RITLB0*/ /*RDTLB0*/
1260: gen_helper_rtlb0(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
1261: break;
1262:
1263: case 4: /*IITLB*/ /*IDTLB*/
1264: gen_helper_itlb(cpu_R[RRR_S], dtlb);
1265: /* This could change memory mapping, so exit tb */
1266: gen_jumpi_check_loop_end(dc, -1);
1267: break;
1268:
1269: case 5: /*PITLB*/ /*PDTLB*/
1270: tcg_gen_movi_i32(cpu_pc, dc->pc);
1271: gen_helper_ptlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
1272: break;
1273:
1274: case 6: /*WITLB*/ /*WDTLB*/
1275: gen_helper_wtlb(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
1276: /* This could change memory mapping, so exit tb */
1277: gen_jumpi_check_loop_end(dc, -1);
1278: break;
1279:
1280: case 7: /*RITLB1*/ /*RDTLB1*/
1281: gen_helper_rtlb1(cpu_R[RRR_T], cpu_R[RRR_S], dtlb);
1282: break;
1283:
1284: default:
1285: tcg_temp_free(dtlb);
1286: RESERVED();
1287: break;
1288: }
1289: tcg_temp_free(dtlb);
1290: }
1291: break;
1292:
1293: case 6: /*RT0*/
1294: gen_window_check2(dc, RRR_R, RRR_T);
1295: switch (RRR_S) {
1296: case 0: /*NEG*/
1297: tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1298: break;
1299:
1300: case 1: /*ABS*/
1301: {
1302: int label = gen_new_label();
1303: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1304: tcg_gen_brcondi_i32(
1305: TCG_COND_GE, cpu_R[RRR_R], 0, label);
1306: tcg_gen_neg_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1307: gen_set_label(label);
1308: }
1309: break;
1310:
1311: default: /*reserved*/
1312: RESERVED();
1313: break;
1314: }
1315: break;
1316:
1317: case 7: /*reserved*/
1318: RESERVED();
1319: break;
1320:
1321: case 8: /*ADD*/
1322: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1323: tcg_gen_add_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1324: break;
1325:
1326: case 9: /*ADD**/
1327: case 10:
1328: case 11:
1329: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1330: {
1331: TCGv_i32 tmp = tcg_temp_new_i32();
1332: tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 8);
1333: tcg_gen_add_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
1334: tcg_temp_free(tmp);
1335: }
1336: break;
1337:
1338: case 12: /*SUB*/
1339: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1340: tcg_gen_sub_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1341: break;
1342:
1343: case 13: /*SUB**/
1344: case 14:
1345: case 15:
1346: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1347: {
1348: TCGv_i32 tmp = tcg_temp_new_i32();
1349: tcg_gen_shli_i32(tmp, cpu_R[RRR_S], OP2 - 12);
1350: tcg_gen_sub_i32(cpu_R[RRR_R], tmp, cpu_R[RRR_T]);
1351: tcg_temp_free(tmp);
1352: }
1353: break;
1354: }
1355: break;
1356:
1357: case 1: /*RST1*/
1358: switch (OP2) {
1359: case 0: /*SLLI*/
1360: case 1:
1361: gen_window_check2(dc, RRR_R, RRR_S);
1362: tcg_gen_shli_i32(cpu_R[RRR_R], cpu_R[RRR_S],
1363: 32 - (RRR_T | ((OP2 & 1) << 4)));
1364: break;
1365:
1366: case 2: /*SRAI*/
1367: case 3:
1368: gen_window_check2(dc, RRR_R, RRR_T);
1369: tcg_gen_sari_i32(cpu_R[RRR_R], cpu_R[RRR_T],
1370: RRR_S | ((OP2 & 1) << 4));
1371: break;
1372:
1373: case 4: /*SRLI*/
1374: gen_window_check2(dc, RRR_R, RRR_T);
1375: tcg_gen_shri_i32(cpu_R[RRR_R], cpu_R[RRR_T], RRR_S);
1376: break;
1377:
1378: case 6: /*XSR*/
1379: {
1380: TCGv_i32 tmp = tcg_temp_new_i32();
1381: if (RSR_SR >= 64) {
1382: gen_check_privilege(dc);
1383: }
1384: gen_window_check1(dc, RRR_T);
1385: tcg_gen_mov_i32(tmp, cpu_R[RRR_T]);
1386: gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
1387: gen_wsr(dc, RSR_SR, tmp);
1388: tcg_temp_free(tmp);
1389: if (!sregnames[RSR_SR]) {
1390: TBD();
1391: }
1392: }
1393: break;
1394:
1395: /*
1396: * Note: 64 bit ops are used here solely because SAR values
1397: * have range 0..63
1398: */
1399: #define gen_shift_reg(cmd, reg) do { \
1400: TCGv_i64 tmp = tcg_temp_new_i64(); \
1401: tcg_gen_extu_i32_i64(tmp, reg); \
1402: tcg_gen_##cmd##_i64(v, v, tmp); \
1403: tcg_gen_trunc_i64_i32(cpu_R[RRR_R], v); \
1404: tcg_temp_free_i64(v); \
1405: tcg_temp_free_i64(tmp); \
1406: } while (0)
1407:
1408: #define gen_shift(cmd) gen_shift_reg(cmd, cpu_SR[SAR])
1409:
1410: case 8: /*SRC*/
1411: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1412: {
1413: TCGv_i64 v = tcg_temp_new_i64();
1414: tcg_gen_concat_i32_i64(v, cpu_R[RRR_T], cpu_R[RRR_S]);
1415: gen_shift(shr);
1416: }
1417: break;
1418:
1419: case 9: /*SRL*/
1420: gen_window_check2(dc, RRR_R, RRR_T);
1421: if (dc->sar_5bit) {
1422: tcg_gen_shr_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
1423: } else {
1424: TCGv_i64 v = tcg_temp_new_i64();
1425: tcg_gen_extu_i32_i64(v, cpu_R[RRR_T]);
1426: gen_shift(shr);
1427: }
1428: break;
1429:
1430: case 10: /*SLL*/
1431: gen_window_check2(dc, RRR_R, RRR_S);
1432: if (dc->sar_m32_5bit) {
1433: tcg_gen_shl_i32(cpu_R[RRR_R], cpu_R[RRR_S], dc->sar_m32);
1434: } else {
1435: TCGv_i64 v = tcg_temp_new_i64();
1436: TCGv_i32 s = tcg_const_i32(32);
1437: tcg_gen_sub_i32(s, s, cpu_SR[SAR]);
1438: tcg_gen_andi_i32(s, s, 0x3f);
1439: tcg_gen_extu_i32_i64(v, cpu_R[RRR_S]);
1440: gen_shift_reg(shl, s);
1441: tcg_temp_free(s);
1442: }
1443: break;
1444:
1445: case 11: /*SRA*/
1446: gen_window_check2(dc, RRR_R, RRR_T);
1447: if (dc->sar_5bit) {
1448: tcg_gen_sar_i32(cpu_R[RRR_R], cpu_R[RRR_T], cpu_SR[SAR]);
1449: } else {
1450: TCGv_i64 v = tcg_temp_new_i64();
1451: tcg_gen_ext_i32_i64(v, cpu_R[RRR_T]);
1452: gen_shift(sar);
1453: }
1454: break;
1455: #undef gen_shift
1456: #undef gen_shift_reg
1457:
1458: case 12: /*MUL16U*/
1459: HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
1460: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1461: {
1462: TCGv_i32 v1 = tcg_temp_new_i32();
1463: TCGv_i32 v2 = tcg_temp_new_i32();
1464: tcg_gen_ext16u_i32(v1, cpu_R[RRR_S]);
1465: tcg_gen_ext16u_i32(v2, cpu_R[RRR_T]);
1466: tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
1467: tcg_temp_free(v2);
1468: tcg_temp_free(v1);
1469: }
1470: break;
1471:
1472: case 13: /*MUL16S*/
1473: HAS_OPTION(XTENSA_OPTION_16_BIT_IMUL);
1474: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1475: {
1476: TCGv_i32 v1 = tcg_temp_new_i32();
1477: TCGv_i32 v2 = tcg_temp_new_i32();
1478: tcg_gen_ext16s_i32(v1, cpu_R[RRR_S]);
1479: tcg_gen_ext16s_i32(v2, cpu_R[RRR_T]);
1480: tcg_gen_mul_i32(cpu_R[RRR_R], v1, v2);
1481: tcg_temp_free(v2);
1482: tcg_temp_free(v1);
1483: }
1484: break;
1485:
1486: default: /*reserved*/
1487: RESERVED();
1488: break;
1489: }
1490: break;
1491:
1492: case 2: /*RST2*/
1493: if (OP2 >= 8) {
1494: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1495: }
1496:
1497: if (OP2 >= 12) {
1498: HAS_OPTION(XTENSA_OPTION_32_BIT_IDIV);
1499: int label = gen_new_label();
1500: tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0, label);
1501: gen_exception_cause(dc, INTEGER_DIVIDE_BY_ZERO_CAUSE);
1502: gen_set_label(label);
1503: }
1504:
1505: switch (OP2) {
1506: #define BOOLEAN_LOGIC(fn, r, s, t) \
1507: do { \
1508: HAS_OPTION(XTENSA_OPTION_BOOLEAN); \
1509: TCGv_i32 tmp1 = tcg_temp_new_i32(); \
1510: TCGv_i32 tmp2 = tcg_temp_new_i32(); \
1511: \
1512: tcg_gen_shri_i32(tmp1, cpu_SR[BR], s); \
1513: tcg_gen_shri_i32(tmp2, cpu_SR[BR], t); \
1514: tcg_gen_##fn##_i32(tmp1, tmp1, tmp2); \
1515: tcg_gen_deposit_i32(cpu_SR[BR], cpu_SR[BR], tmp1, r, 1); \
1516: tcg_temp_free(tmp1); \
1517: tcg_temp_free(tmp2); \
1518: } while (0)
1519:
1520: case 0: /*ANDBp*/
1521: BOOLEAN_LOGIC(and, RRR_R, RRR_S, RRR_T);
1522: break;
1523:
1524: case 1: /*ANDBCp*/
1525: BOOLEAN_LOGIC(andc, RRR_R, RRR_S, RRR_T);
1526: break;
1527:
1528: case 2: /*ORBp*/
1529: BOOLEAN_LOGIC(or, RRR_R, RRR_S, RRR_T);
1530: break;
1531:
1532: case 3: /*ORBCp*/
1533: BOOLEAN_LOGIC(orc, RRR_R, RRR_S, RRR_T);
1534: break;
1535:
1536: case 4: /*XORBp*/
1537: BOOLEAN_LOGIC(xor, RRR_R, RRR_S, RRR_T);
1538: break;
1539:
1540: #undef BOOLEAN_LOGIC
1541:
1542: case 8: /*MULLi*/
1543: HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL);
1544: tcg_gen_mul_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1545: break;
1546:
1547: case 10: /*MULUHi*/
1548: case 11: /*MULSHi*/
1549: HAS_OPTION(XTENSA_OPTION_32_BIT_IMUL_HIGH);
1550: {
1551: TCGv_i64 r = tcg_temp_new_i64();
1552: TCGv_i64 s = tcg_temp_new_i64();
1553: TCGv_i64 t = tcg_temp_new_i64();
1554:
1555: if (OP2 == 10) {
1556: tcg_gen_extu_i32_i64(s, cpu_R[RRR_S]);
1557: tcg_gen_extu_i32_i64(t, cpu_R[RRR_T]);
1558: } else {
1559: tcg_gen_ext_i32_i64(s, cpu_R[RRR_S]);
1560: tcg_gen_ext_i32_i64(t, cpu_R[RRR_T]);
1561: }
1562: tcg_gen_mul_i64(r, s, t);
1563: tcg_gen_shri_i64(r, r, 32);
1564: tcg_gen_trunc_i64_i32(cpu_R[RRR_R], r);
1565:
1566: tcg_temp_free_i64(r);
1567: tcg_temp_free_i64(s);
1568: tcg_temp_free_i64(t);
1569: }
1570: break;
1571:
1572: case 12: /*QUOUi*/
1573: tcg_gen_divu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1574: break;
1575:
1576: case 13: /*QUOSi*/
1577: case 15: /*REMSi*/
1578: {
1579: int label1 = gen_new_label();
1580: int label2 = gen_new_label();
1581:
1582: tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_S], 0x80000000,
1583: label1);
1584: tcg_gen_brcondi_i32(TCG_COND_NE, cpu_R[RRR_T], 0xffffffff,
1585: label1);
1586: tcg_gen_movi_i32(cpu_R[RRR_R],
1587: OP2 == 13 ? 0x80000000 : 0);
1588: tcg_gen_br(label2);
1589: gen_set_label(label1);
1590: if (OP2 == 13) {
1591: tcg_gen_div_i32(cpu_R[RRR_R],
1592: cpu_R[RRR_S], cpu_R[RRR_T]);
1593: } else {
1594: tcg_gen_rem_i32(cpu_R[RRR_R],
1595: cpu_R[RRR_S], cpu_R[RRR_T]);
1596: }
1597: gen_set_label(label2);
1598: }
1599: break;
1600:
1601: case 14: /*REMUi*/
1602: tcg_gen_remu_i32(cpu_R[RRR_R], cpu_R[RRR_S], cpu_R[RRR_T]);
1603: break;
1604:
1605: default: /*reserved*/
1606: RESERVED();
1607: break;
1608: }
1609: break;
1610:
1611: case 3: /*RST3*/
1612: switch (OP2) {
1613: case 0: /*RSR*/
1614: if (RSR_SR >= 64) {
1615: gen_check_privilege(dc);
1616: }
1617: gen_window_check1(dc, RRR_T);
1618: gen_rsr(dc, cpu_R[RRR_T], RSR_SR);
1619: if (!sregnames[RSR_SR]) {
1620: TBD();
1621: }
1622: break;
1623:
1624: case 1: /*WSR*/
1625: if (RSR_SR >= 64) {
1626: gen_check_privilege(dc);
1627: }
1628: gen_window_check1(dc, RRR_T);
1629: gen_wsr(dc, RSR_SR, cpu_R[RRR_T]);
1630: if (!sregnames[RSR_SR]) {
1631: TBD();
1632: }
1633: break;
1634:
1635: case 2: /*SEXTu*/
1636: HAS_OPTION(XTENSA_OPTION_MISC_OP_SEXT);
1637: gen_window_check2(dc, RRR_R, RRR_S);
1638: {
1639: int shift = 24 - RRR_T;
1640:
1641: if (shift == 24) {
1642: tcg_gen_ext8s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1643: } else if (shift == 16) {
1644: tcg_gen_ext16s_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1645: } else {
1646: TCGv_i32 tmp = tcg_temp_new_i32();
1647: tcg_gen_shli_i32(tmp, cpu_R[RRR_S], shift);
1648: tcg_gen_sari_i32(cpu_R[RRR_R], tmp, shift);
1649: tcg_temp_free(tmp);
1650: }
1651: }
1652: break;
1653:
1654: case 3: /*CLAMPSu*/
1655: HAS_OPTION(XTENSA_OPTION_MISC_OP_CLAMPS);
1656: gen_window_check2(dc, RRR_R, RRR_S);
1657: {
1658: TCGv_i32 tmp1 = tcg_temp_new_i32();
1659: TCGv_i32 tmp2 = tcg_temp_new_i32();
1660: int label = gen_new_label();
1661:
1662: tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 24 - RRR_T);
1663: tcg_gen_xor_i32(tmp2, tmp1, cpu_R[RRR_S]);
1664: tcg_gen_andi_i32(tmp2, tmp2, 0xffffffff << (RRR_T + 7));
1665: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1666: tcg_gen_brcondi_i32(TCG_COND_EQ, tmp2, 0, label);
1667:
1668: tcg_gen_sari_i32(tmp1, cpu_R[RRR_S], 31);
1669: tcg_gen_xori_i32(cpu_R[RRR_R], tmp1,
1670: 0xffffffff >> (25 - RRR_T));
1671:
1672: gen_set_label(label);
1673:
1674: tcg_temp_free(tmp1);
1675: tcg_temp_free(tmp2);
1676: }
1677: break;
1678:
1679: case 4: /*MINu*/
1680: case 5: /*MAXu*/
1681: case 6: /*MINUu*/
1682: case 7: /*MAXUu*/
1683: HAS_OPTION(XTENSA_OPTION_MISC_OP_MINMAX);
1684: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1685: {
1686: static const TCGCond cond[] = {
1687: TCG_COND_LE,
1688: TCG_COND_GE,
1689: TCG_COND_LEU,
1690: TCG_COND_GEU
1691: };
1692: int label = gen_new_label();
1693:
1694: if (RRR_R != RRR_T) {
1695: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1696: tcg_gen_brcond_i32(cond[OP2 - 4],
1697: cpu_R[RRR_S], cpu_R[RRR_T], label);
1698: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_T]);
1699: } else {
1700: tcg_gen_brcond_i32(cond[OP2 - 4],
1701: cpu_R[RRR_T], cpu_R[RRR_S], label);
1702: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1703: }
1704: gen_set_label(label);
1705: }
1706: break;
1707:
1708: case 8: /*MOVEQZ*/
1709: case 9: /*MOVNEZ*/
1710: case 10: /*MOVLTZ*/
1711: case 11: /*MOVGEZ*/
1712: gen_window_check3(dc, RRR_R, RRR_S, RRR_T);
1713: {
1714: static const TCGCond cond[] = {
1715: TCG_COND_NE,
1716: TCG_COND_EQ,
1717: TCG_COND_GE,
1718: TCG_COND_LT
1719: };
1720: int label = gen_new_label();
1721: tcg_gen_brcondi_i32(cond[OP2 - 8], cpu_R[RRR_T], 0, label);
1722: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1723: gen_set_label(label);
1724: }
1725: break;
1726:
1727: case 12: /*MOVFp*/
1728: case 13: /*MOVTp*/
1729: HAS_OPTION(XTENSA_OPTION_BOOLEAN);
1730: gen_window_check2(dc, RRR_R, RRR_S);
1731: {
1732: int label = gen_new_label();
1733: TCGv_i32 tmp = tcg_temp_new_i32();
1734:
1735: tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRR_T);
1736: tcg_gen_brcondi_i32(
1737: OP2 & 1 ? TCG_COND_EQ : TCG_COND_NE,
1738: tmp, 0, label);
1739: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_R[RRR_S]);
1740: gen_set_label(label);
1741: tcg_temp_free(tmp);
1742: }
1743: break;
1744:
1745: case 14: /*RUR*/
1746: gen_window_check1(dc, RRR_R);
1747: {
1748: int st = (RRR_S << 4) + RRR_T;
1749: if (uregnames[st]) {
1750: tcg_gen_mov_i32(cpu_R[RRR_R], cpu_UR[st]);
1751: } else {
1752: qemu_log("RUR %d not implemented, ", st);
1753: TBD();
1754: }
1755: }
1756: break;
1757:
1758: case 15: /*WUR*/
1759: gen_window_check1(dc, RRR_T);
1760: {
1761: if (uregnames[RSR_SR]) {
1762: tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
1763: } else {
1764: qemu_log("WUR %d not implemented, ", RSR_SR);
1765: TBD();
1766: }
1767: }
1768: break;
1769:
1770: }
1771: break;
1772:
1773: case 4: /*EXTUI*/
1774: case 5:
1775: gen_window_check2(dc, RRR_R, RRR_T);
1776: {
1777: int shiftimm = RRR_S | (OP1 << 4);
1778: int maskimm = (1 << (OP2 + 1)) - 1;
1779:
1780: TCGv_i32 tmp = tcg_temp_new_i32();
1781: tcg_gen_shri_i32(tmp, cpu_R[RRR_T], shiftimm);
1782: tcg_gen_andi_i32(cpu_R[RRR_R], tmp, maskimm);
1783: tcg_temp_free(tmp);
1784: }
1785: break;
1786:
1787: case 6: /*CUST0*/
1788: RESERVED();
1789: break;
1790:
1791: case 7: /*CUST1*/
1792: RESERVED();
1793: break;
1794:
1795: case 8: /*LSCXp*/
1796: HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
1797: TBD();
1798: break;
1799:
1800: case 9: /*LSC4*/
1801: gen_window_check2(dc, RRR_S, RRR_T);
1802: switch (OP2) {
1803: case 0: /*L32E*/
1804: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
1805: gen_check_privilege(dc);
1806: {
1807: TCGv_i32 addr = tcg_temp_new_i32();
1808: tcg_gen_addi_i32(addr, cpu_R[RRR_S],
1809: (0xffffffc0 | (RRR_R << 2)));
1810: tcg_gen_qemu_ld32u(cpu_R[RRR_T], addr, dc->ring);
1811: tcg_temp_free(addr);
1812: }
1813: break;
1814:
1815: case 4: /*S32E*/
1816: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
1817: gen_check_privilege(dc);
1818: {
1819: TCGv_i32 addr = tcg_temp_new_i32();
1820: tcg_gen_addi_i32(addr, cpu_R[RRR_S],
1821: (0xffffffc0 | (RRR_R << 2)));
1822: tcg_gen_qemu_st32(cpu_R[RRR_T], addr, dc->ring);
1823: tcg_temp_free(addr);
1824: }
1825: break;
1826:
1827: default:
1828: RESERVED();
1829: break;
1830: }
1831: break;
1832:
1833: case 10: /*FP0*/
1834: HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
1835: TBD();
1836: break;
1837:
1838: case 11: /*FP1*/
1839: HAS_OPTION(XTENSA_OPTION_FP_COPROCESSOR);
1840: TBD();
1841: break;
1842:
1843: default: /*reserved*/
1844: RESERVED();
1845: break;
1846: }
1847: break;
1848:
1849: case 1: /*L32R*/
1850: gen_window_check1(dc, RRR_T);
1851: {
1852: TCGv_i32 tmp = tcg_const_i32(
1853: ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
1854: 0 : ((dc->pc + 3) & ~3)) +
1855: (0xfffc0000 | (RI16_IMM16 << 2)));
1856:
1857: if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
1858: tcg_gen_add_i32(tmp, tmp, dc->litbase);
1859: }
1860: tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
1861: tcg_temp_free(tmp);
1862: }
1863: break;
1864:
1865: case 2: /*LSAI*/
1866: #define gen_load_store(type, shift) do { \
1867: TCGv_i32 addr = tcg_temp_new_i32(); \
1868: gen_window_check2(dc, RRI8_S, RRI8_T); \
1869: tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
1870: if (shift) { \
1871: gen_load_store_alignment(dc, shift, addr, false); \
1872: } \
1873: tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
1874: tcg_temp_free(addr); \
1875: } while (0)
1876:
1877: switch (RRI8_R) {
1878: case 0: /*L8UI*/
1879: gen_load_store(ld8u, 0);
1880: break;
1881:
1882: case 1: /*L16UI*/
1883: gen_load_store(ld16u, 1);
1884: break;
1885:
1886: case 2: /*L32I*/
1887: gen_load_store(ld32u, 2);
1888: break;
1889:
1890: case 4: /*S8I*/
1891: gen_load_store(st8, 0);
1892: break;
1893:
1894: case 5: /*S16I*/
1895: gen_load_store(st16, 1);
1896: break;
1897:
1898: case 6: /*S32I*/
1899: gen_load_store(st32, 2);
1900: break;
1901:
1902: case 7: /*CACHEc*/
1903: if (RRI8_T < 8) {
1904: HAS_OPTION(XTENSA_OPTION_DCACHE);
1905: }
1906:
1907: switch (RRI8_T) {
1908: case 0: /*DPFRc*/
1909: break;
1910:
1911: case 1: /*DPFWc*/
1912: break;
1913:
1914: case 2: /*DPFROc*/
1915: break;
1916:
1917: case 3: /*DPFWOc*/
1918: break;
1919:
1920: case 4: /*DHWBc*/
1921: break;
1922:
1923: case 5: /*DHWBIc*/
1924: break;
1925:
1926: case 6: /*DHIc*/
1927: break;
1928:
1929: case 7: /*DIIc*/
1930: break;
1931:
1932: case 8: /*DCEc*/
1933: switch (OP1) {
1934: case 0: /*DPFLl*/
1935: HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
1936: break;
1937:
1938: case 2: /*DHUl*/
1939: HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
1940: break;
1941:
1942: case 3: /*DIUl*/
1943: HAS_OPTION(XTENSA_OPTION_DCACHE_INDEX_LOCK);
1944: break;
1945:
1946: case 4: /*DIWBc*/
1947: HAS_OPTION(XTENSA_OPTION_DCACHE);
1948: break;
1949:
1950: case 5: /*DIWBIc*/
1951: HAS_OPTION(XTENSA_OPTION_DCACHE);
1952: break;
1953:
1954: default: /*reserved*/
1955: RESERVED();
1956: break;
1957:
1958: }
1959: break;
1960:
1961: case 12: /*IPFc*/
1962: HAS_OPTION(XTENSA_OPTION_ICACHE);
1963: break;
1964:
1965: case 13: /*ICEc*/
1966: switch (OP1) {
1967: case 0: /*IPFLl*/
1968: HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
1969: break;
1970:
1971: case 2: /*IHUl*/
1972: HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
1973: break;
1974:
1975: case 3: /*IIUl*/
1976: HAS_OPTION(XTENSA_OPTION_ICACHE_INDEX_LOCK);
1977: break;
1978:
1979: default: /*reserved*/
1980: RESERVED();
1981: break;
1982: }
1983: break;
1984:
1985: case 14: /*IHIc*/
1986: HAS_OPTION(XTENSA_OPTION_ICACHE);
1987: break;
1988:
1989: case 15: /*IIIc*/
1990: HAS_OPTION(XTENSA_OPTION_ICACHE);
1991: break;
1992:
1993: default: /*reserved*/
1994: RESERVED();
1995: break;
1996: }
1997: break;
1998:
1999: case 9: /*L16SI*/
2000: gen_load_store(ld16s, 1);
2001: break;
2002: #undef gen_load_store
2003:
2004: case 10: /*MOVI*/
2005: gen_window_check1(dc, RRI8_T);
2006: tcg_gen_movi_i32(cpu_R[RRI8_T],
2007: RRI8_IMM8 | (RRI8_S << 8) |
2008: ((RRI8_S & 0x8) ? 0xfffff000 : 0));
2009: break;
2010:
2011: #define gen_load_store_no_hw_align(type) do { \
2012: TCGv_i32 addr = tcg_temp_local_new_i32(); \
2013: gen_window_check2(dc, RRI8_S, RRI8_T); \
2014: tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
2015: gen_load_store_alignment(dc, 2, addr, true); \
2016: tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
2017: tcg_temp_free(addr); \
2018: } while (0)
2019:
2020: case 11: /*L32AIy*/
2021: HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
2022: gen_load_store_no_hw_align(ld32u); /*TODO acquire?*/
2023: break;
2024:
2025: case 12: /*ADDI*/
2026: gen_window_check2(dc, RRI8_S, RRI8_T);
2027: tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE);
2028: break;
2029:
2030: case 13: /*ADDMI*/
2031: gen_window_check2(dc, RRI8_S, RRI8_T);
2032: tcg_gen_addi_i32(cpu_R[RRI8_T], cpu_R[RRI8_S], RRI8_IMM8_SE << 8);
2033: break;
2034:
2035: case 14: /*S32C1Iy*/
2036: HAS_OPTION(XTENSA_OPTION_CONDITIONAL_STORE);
2037: gen_window_check2(dc, RRI8_S, RRI8_T);
2038: {
2039: int label = gen_new_label();
2040: TCGv_i32 tmp = tcg_temp_local_new_i32();
2041: TCGv_i32 addr = tcg_temp_local_new_i32();
2042:
2043: tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
2044: tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
2045: gen_load_store_alignment(dc, 2, addr, true);
2046: tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
2047: tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
2048: cpu_SR[SCOMPARE1], label);
2049:
2050: tcg_gen_qemu_st32(tmp, addr, dc->cring);
2051:
2052: gen_set_label(label);
2053: tcg_temp_free(addr);
2054: tcg_temp_free(tmp);
2055: }
2056: break;
2057:
2058: case 15: /*S32RIy*/
2059: HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
2060: gen_load_store_no_hw_align(st32); /*TODO release?*/
2061: break;
2062: #undef gen_load_store_no_hw_align
2063:
2064: default: /*reserved*/
2065: RESERVED();
2066: break;
2067: }
2068: break;
2069:
2070: case 3: /*LSCIp*/
2071: HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
2072: TBD();
2073: break;
2074:
2075: case 4: /*MAC16d*/
2076: HAS_OPTION(XTENSA_OPTION_MAC16);
2077: {
2078: enum {
2079: MAC16_UMUL = 0x0,
2080: MAC16_MUL = 0x4,
2081: MAC16_MULA = 0x8,
2082: MAC16_MULS = 0xc,
2083: MAC16_NONE = 0xf,
2084: } op = OP1 & 0xc;
2085: bool is_m1_sr = (OP2 & 0x3) == 2;
2086: bool is_m2_sr = (OP2 & 0xc) == 0;
2087: uint32_t ld_offset = 0;
2088:
2089: if (OP2 > 9) {
2090: RESERVED();
2091: }
2092:
2093: switch (OP2 & 2) {
2094: case 0: /*MACI?/MACC?*/
2095: is_m1_sr = true;
2096: ld_offset = (OP2 & 1) ? -4 : 4;
2097:
2098: if (OP2 >= 8) { /*MACI/MACC*/
2099: if (OP1 == 0) { /*LDINC/LDDEC*/
2100: op = MAC16_NONE;
2101: } else {
2102: RESERVED();
2103: }
2104: } else if (op != MAC16_MULA) { /*MULA.*.*.LDINC/LDDEC*/
2105: RESERVED();
2106: }
2107: break;
2108:
2109: case 2: /*MACD?/MACA?*/
2110: if (op == MAC16_UMUL && OP2 != 7) { /*UMUL only in MACAA*/
2111: RESERVED();
2112: }
2113: break;
2114: }
2115:
2116: if (op != MAC16_NONE) {
2117: if (!is_m1_sr) {
2118: gen_window_check1(dc, RRR_S);
2119: }
2120: if (!is_m2_sr) {
2121: gen_window_check1(dc, RRR_T);
2122: }
2123: }
2124:
2125: {
2126: TCGv_i32 vaddr = tcg_temp_new_i32();
2127: TCGv_i32 mem32 = tcg_temp_new_i32();
2128:
2129: if (ld_offset) {
2130: gen_window_check1(dc, RRR_S);
2131: tcg_gen_addi_i32(vaddr, cpu_R[RRR_S], ld_offset);
2132: gen_load_store_alignment(dc, 2, vaddr, false);
2133: tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
2134: }
2135: if (op != MAC16_NONE) {
2136: TCGv_i32 m1 = gen_mac16_m(
2137: is_m1_sr ? cpu_SR[MR + RRR_X] : cpu_R[RRR_S],
2138: OP1 & 1, op == MAC16_UMUL);
2139: TCGv_i32 m2 = gen_mac16_m(
2140: is_m2_sr ? cpu_SR[MR + 2 + RRR_Y] : cpu_R[RRR_T],
2141: OP1 & 2, op == MAC16_UMUL);
2142:
2143: if (op == MAC16_MUL || op == MAC16_UMUL) {
2144: tcg_gen_mul_i32(cpu_SR[ACCLO], m1, m2);
2145: if (op == MAC16_UMUL) {
2146: tcg_gen_movi_i32(cpu_SR[ACCHI], 0);
2147: } else {
2148: tcg_gen_sari_i32(cpu_SR[ACCHI], cpu_SR[ACCLO], 31);
2149: }
2150: } else {
2151: TCGv_i32 res = tcg_temp_new_i32();
2152: TCGv_i64 res64 = tcg_temp_new_i64();
2153: TCGv_i64 tmp = tcg_temp_new_i64();
2154:
2155: tcg_gen_mul_i32(res, m1, m2);
2156: tcg_gen_ext_i32_i64(res64, res);
2157: tcg_gen_concat_i32_i64(tmp,
2158: cpu_SR[ACCLO], cpu_SR[ACCHI]);
2159: if (op == MAC16_MULA) {
2160: tcg_gen_add_i64(tmp, tmp, res64);
2161: } else {
2162: tcg_gen_sub_i64(tmp, tmp, res64);
2163: }
2164: tcg_gen_trunc_i64_i32(cpu_SR[ACCLO], tmp);
2165: tcg_gen_shri_i64(tmp, tmp, 32);
2166: tcg_gen_trunc_i64_i32(cpu_SR[ACCHI], tmp);
2167: tcg_gen_ext8s_i32(cpu_SR[ACCHI], cpu_SR[ACCHI]);
2168:
2169: tcg_temp_free(res);
2170: tcg_temp_free_i64(res64);
2171: tcg_temp_free_i64(tmp);
2172: }
2173: tcg_temp_free(m1);
2174: tcg_temp_free(m2);
2175: }
2176: if (ld_offset) {
2177: tcg_gen_mov_i32(cpu_R[RRR_S], vaddr);
2178: tcg_gen_mov_i32(cpu_SR[MR + RRR_W], mem32);
2179: }
2180: tcg_temp_free(vaddr);
2181: tcg_temp_free(mem32);
2182: }
2183: }
2184: break;
2185:
2186: case 5: /*CALLN*/
2187: switch (CALL_N) {
2188: case 0: /*CALL0*/
2189: tcg_gen_movi_i32(cpu_R[0], dc->next_pc);
2190: gen_jumpi(dc, (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
2191: break;
2192:
2193: case 1: /*CALL4w*/
2194: case 2: /*CALL8w*/
2195: case 3: /*CALL12w*/
2196: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
2197: gen_window_check1(dc, CALL_N << 2);
2198: gen_callwi(dc, CALL_N,
2199: (dc->pc & ~3) + (CALL_OFFSET_SE << 2) + 4, 0);
2200: break;
2201: }
2202: break;
2203:
2204: case 6: /*SI*/
2205: switch (CALL_N) {
2206: case 0: /*J*/
2207: gen_jumpi(dc, dc->pc + 4 + CALL_OFFSET_SE, 0);
2208: break;
2209:
2210: case 1: /*BZ*/
2211: gen_window_check1(dc, BRI12_S);
2212: {
2213: static const TCGCond cond[] = {
2214: TCG_COND_EQ, /*BEQZ*/
2215: TCG_COND_NE, /*BNEZ*/
2216: TCG_COND_LT, /*BLTZ*/
2217: TCG_COND_GE, /*BGEZ*/
2218: };
2219:
2220: gen_brcondi(dc, cond[BRI12_M & 3], cpu_R[BRI12_S], 0,
2221: 4 + BRI12_IMM12_SE);
2222: }
2223: break;
2224:
2225: case 2: /*BI0*/
2226: gen_window_check1(dc, BRI8_S);
2227: {
2228: static const TCGCond cond[] = {
2229: TCG_COND_EQ, /*BEQI*/
2230: TCG_COND_NE, /*BNEI*/
2231: TCG_COND_LT, /*BLTI*/
2232: TCG_COND_GE, /*BGEI*/
2233: };
2234:
2235: gen_brcondi(dc, cond[BRI8_M & 3],
2236: cpu_R[BRI8_S], B4CONST[BRI8_R], 4 + BRI8_IMM8_SE);
2237: }
2238: break;
2239:
2240: case 3: /*BI1*/
2241: switch (BRI8_M) {
2242: case 0: /*ENTRYw*/
2243: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
2244: {
2245: TCGv_i32 pc = tcg_const_i32(dc->pc);
2246: TCGv_i32 s = tcg_const_i32(BRI12_S);
2247: TCGv_i32 imm = tcg_const_i32(BRI12_IMM12);
2248: gen_advance_ccount(dc);
2249: gen_helper_entry(pc, s, imm);
2250: tcg_temp_free(imm);
2251: tcg_temp_free(s);
2252: tcg_temp_free(pc);
2253: reset_used_window(dc);
2254: }
2255: break;
2256:
2257: case 1: /*B1*/
2258: switch (BRI8_R) {
2259: case 0: /*BFp*/
2260: case 1: /*BTp*/
2261: HAS_OPTION(XTENSA_OPTION_BOOLEAN);
2262: {
2263: TCGv_i32 tmp = tcg_temp_new_i32();
2264: tcg_gen_andi_i32(tmp, cpu_SR[BR], 1 << RRI8_S);
2265: gen_brcondi(dc,
2266: BRI8_R == 1 ? TCG_COND_NE : TCG_COND_EQ,
2267: tmp, 0, 4 + RRI8_IMM8_SE);
2268: tcg_temp_free(tmp);
2269: }
2270: break;
2271:
2272: case 8: /*LOOP*/
2273: case 9: /*LOOPNEZ*/
2274: case 10: /*LOOPGTZ*/
2275: HAS_OPTION(XTENSA_OPTION_LOOP);
2276: gen_window_check1(dc, RRI8_S);
2277: {
2278: uint32_t lend = dc->pc + RRI8_IMM8 + 4;
2279: TCGv_i32 tmp = tcg_const_i32(lend);
2280:
2281: tcg_gen_subi_i32(cpu_SR[LCOUNT], cpu_R[RRI8_S], 1);
2282: tcg_gen_movi_i32(cpu_SR[LBEG], dc->next_pc);
1.1.1.2 ! root 2283: gen_helper_wsr_lend(tmp);
1.1 root 2284: tcg_temp_free(tmp);
2285:
2286: if (BRI8_R > 8) {
2287: int label = gen_new_label();
2288: tcg_gen_brcondi_i32(
2289: BRI8_R == 9 ? TCG_COND_NE : TCG_COND_GT,
2290: cpu_R[RRI8_S], 0, label);
2291: gen_jumpi(dc, lend, 1);
2292: gen_set_label(label);
2293: }
2294:
2295: gen_jumpi(dc, dc->next_pc, 0);
2296: }
2297: break;
2298:
2299: default: /*reserved*/
2300: RESERVED();
2301: break;
2302:
2303: }
2304: break;
2305:
2306: case 2: /*BLTUI*/
2307: case 3: /*BGEUI*/
2308: gen_window_check1(dc, BRI8_S);
2309: gen_brcondi(dc, BRI8_M == 2 ? TCG_COND_LTU : TCG_COND_GEU,
2310: cpu_R[BRI8_S], B4CONSTU[BRI8_R], 4 + BRI8_IMM8_SE);
2311: break;
2312: }
2313: break;
2314:
2315: }
2316: break;
2317:
2318: case 7: /*B*/
2319: {
2320: TCGCond eq_ne = (RRI8_R & 8) ? TCG_COND_NE : TCG_COND_EQ;
2321:
2322: switch (RRI8_R & 7) {
2323: case 0: /*BNONE*/ /*BANY*/
2324: gen_window_check2(dc, RRI8_S, RRI8_T);
2325: {
2326: TCGv_i32 tmp = tcg_temp_new_i32();
2327: tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
2328: gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
2329: tcg_temp_free(tmp);
2330: }
2331: break;
2332:
2333: case 1: /*BEQ*/ /*BNE*/
2334: case 2: /*BLT*/ /*BGE*/
2335: case 3: /*BLTU*/ /*BGEU*/
2336: gen_window_check2(dc, RRI8_S, RRI8_T);
2337: {
2338: static const TCGCond cond[] = {
2339: [1] = TCG_COND_EQ,
2340: [2] = TCG_COND_LT,
2341: [3] = TCG_COND_LTU,
2342: [9] = TCG_COND_NE,
2343: [10] = TCG_COND_GE,
2344: [11] = TCG_COND_GEU,
2345: };
2346: gen_brcond(dc, cond[RRI8_R], cpu_R[RRI8_S], cpu_R[RRI8_T],
2347: 4 + RRI8_IMM8_SE);
2348: }
2349: break;
2350:
2351: case 4: /*BALL*/ /*BNALL*/
2352: gen_window_check2(dc, RRI8_S, RRI8_T);
2353: {
2354: TCGv_i32 tmp = tcg_temp_new_i32();
2355: tcg_gen_and_i32(tmp, cpu_R[RRI8_S], cpu_R[RRI8_T]);
2356: gen_brcond(dc, eq_ne, tmp, cpu_R[RRI8_T],
2357: 4 + RRI8_IMM8_SE);
2358: tcg_temp_free(tmp);
2359: }
2360: break;
2361:
2362: case 5: /*BBC*/ /*BBS*/
2363: gen_window_check2(dc, RRI8_S, RRI8_T);
2364: {
2365: TCGv_i32 bit = tcg_const_i32(1);
2366: TCGv_i32 tmp = tcg_temp_new_i32();
2367: tcg_gen_andi_i32(tmp, cpu_R[RRI8_T], 0x1f);
2368: tcg_gen_shl_i32(bit, bit, tmp);
2369: tcg_gen_and_i32(tmp, cpu_R[RRI8_S], bit);
2370: gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
2371: tcg_temp_free(tmp);
2372: tcg_temp_free(bit);
2373: }
2374: break;
2375:
2376: case 6: /*BBCI*/ /*BBSI*/
2377: case 7:
2378: gen_window_check1(dc, RRI8_S);
2379: {
2380: TCGv_i32 tmp = tcg_temp_new_i32();
2381: tcg_gen_andi_i32(tmp, cpu_R[RRI8_S],
2382: 1 << (((RRI8_R & 1) << 4) | RRI8_T));
2383: gen_brcondi(dc, eq_ne, tmp, 0, 4 + RRI8_IMM8_SE);
2384: tcg_temp_free(tmp);
2385: }
2386: break;
2387:
2388: }
2389: }
2390: break;
2391:
2392: #define gen_narrow_load_store(type) do { \
2393: TCGv_i32 addr = tcg_temp_new_i32(); \
2394: gen_window_check2(dc, RRRN_S, RRRN_T); \
2395: tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
2396: gen_load_store_alignment(dc, 2, addr, false); \
2397: tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
2398: tcg_temp_free(addr); \
2399: } while (0)
2400:
2401: case 8: /*L32I.Nn*/
2402: gen_narrow_load_store(ld32u);
2403: break;
2404:
2405: case 9: /*S32I.Nn*/
2406: gen_narrow_load_store(st32);
2407: break;
2408: #undef gen_narrow_load_store
2409:
2410: case 10: /*ADD.Nn*/
2411: gen_window_check3(dc, RRRN_R, RRRN_S, RRRN_T);
2412: tcg_gen_add_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], cpu_R[RRRN_T]);
2413: break;
2414:
2415: case 11: /*ADDI.Nn*/
2416: gen_window_check2(dc, RRRN_R, RRRN_S);
2417: tcg_gen_addi_i32(cpu_R[RRRN_R], cpu_R[RRRN_S], RRRN_T ? RRRN_T : -1);
2418: break;
2419:
2420: case 12: /*ST2n*/
2421: gen_window_check1(dc, RRRN_S);
2422: if (RRRN_T < 8) { /*MOVI.Nn*/
2423: tcg_gen_movi_i32(cpu_R[RRRN_S],
2424: RRRN_R | (RRRN_T << 4) |
2425: ((RRRN_T & 6) == 6 ? 0xffffff80 : 0));
2426: } else { /*BEQZ.Nn*/ /*BNEZ.Nn*/
2427: TCGCond eq_ne = (RRRN_T & 4) ? TCG_COND_NE : TCG_COND_EQ;
2428:
2429: gen_brcondi(dc, eq_ne, cpu_R[RRRN_S], 0,
2430: 4 + (RRRN_R | ((RRRN_T & 3) << 4)));
2431: }
2432: break;
2433:
2434: case 13: /*ST3n*/
2435: switch (RRRN_R) {
2436: case 0: /*MOV.Nn*/
2437: gen_window_check2(dc, RRRN_S, RRRN_T);
2438: tcg_gen_mov_i32(cpu_R[RRRN_T], cpu_R[RRRN_S]);
2439: break;
2440:
2441: case 15: /*S3*/
2442: switch (RRRN_T) {
2443: case 0: /*RET.Nn*/
2444: gen_jump(dc, cpu_R[0]);
2445: break;
2446:
2447: case 1: /*RETW.Nn*/
2448: HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER);
2449: {
2450: TCGv_i32 tmp = tcg_const_i32(dc->pc);
2451: gen_advance_ccount(dc);
2452: gen_helper_retw(tmp, tmp);
2453: gen_jump(dc, tmp);
2454: tcg_temp_free(tmp);
2455: }
2456: break;
2457:
2458: case 2: /*BREAK.Nn*/
1.1.1.2 ! root 2459: HAS_OPTION(XTENSA_OPTION_DEBUG);
! 2460: if (dc->debug) {
! 2461: gen_debug_exception(dc, DEBUGCAUSE_BN);
! 2462: }
1.1 root 2463: break;
2464:
2465: case 3: /*NOP.Nn*/
2466: break;
2467:
2468: case 6: /*ILL.Nn*/
2469: gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
2470: break;
2471:
2472: default: /*reserved*/
2473: RESERVED();
2474: break;
2475: }
2476: break;
2477:
2478: default: /*reserved*/
2479: RESERVED();
2480: break;
2481: }
2482: break;
2483:
2484: default: /*reserved*/
2485: RESERVED();
2486: break;
2487: }
2488:
2489: gen_check_loop_end(dc, 0);
2490: dc->pc = dc->next_pc;
2491:
2492: return;
2493:
2494: invalid_opcode:
2495: qemu_log("INVALID(pc = %08x)\n", dc->pc);
2496: gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE);
2497: #undef HAS_OPTION
2498: }
2499:
1.1.1.2 ! root 2500: static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
1.1 root 2501: {
2502: CPUBreakpoint *bp;
2503:
2504: if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
2505: QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
2506: if (bp->pc == dc->pc) {
2507: tcg_gen_movi_i32(cpu_pc, dc->pc);
2508: gen_exception(dc, EXCP_DEBUG);
2509: dc->is_jmp = DISAS_UPDATE;
2510: }
2511: }
2512: }
2513: }
2514:
1.1.1.2 ! root 2515: static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
! 2516: {
! 2517: unsigned i;
! 2518:
! 2519: for (i = 0; i < dc->config->nibreak; ++i) {
! 2520: if ((env->sregs[IBREAKENABLE] & (1 << i)) &&
! 2521: env->sregs[IBREAKA + i] == dc->pc) {
! 2522: gen_debug_exception(dc, DEBUGCAUSE_IB);
! 2523: break;
! 2524: }
! 2525: }
! 2526: }
! 2527:
1.1 root 2528: static void gen_intermediate_code_internal(
1.1.1.2 ! root 2529: CPUXtensaState *env, TranslationBlock *tb, int search_pc)
1.1 root 2530: {
2531: DisasContext dc;
2532: int insn_count = 0;
2533: int j, lj = -1;
2534: uint16_t *gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2535: int max_insns = tb->cflags & CF_COUNT_MASK;
2536: uint32_t pc_start = tb->pc;
2537: uint32_t next_page_start =
2538: (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2539:
2540: if (max_insns == 0) {
2541: max_insns = CF_COUNT_MASK;
2542: }
2543:
2544: dc.config = env->config;
2545: dc.singlestep_enabled = env->singlestep_enabled;
2546: dc.tb = tb;
2547: dc.pc = pc_start;
2548: dc.ring = tb->flags & XTENSA_TBFLAG_RING_MASK;
2549: dc.cring = (tb->flags & XTENSA_TBFLAG_EXCM) ? 0 : dc.ring;
2550: dc.lbeg = env->sregs[LBEG];
2551: dc.lend = env->sregs[LEND];
2552: dc.is_jmp = DISAS_NEXT;
2553: dc.ccount_delta = 0;
1.1.1.2 ! root 2554: dc.debug = tb->flags & XTENSA_TBFLAG_DEBUG;
! 2555: dc.icount = tb->flags & XTENSA_TBFLAG_ICOUNT;
1.1 root 2556:
2557: init_litbase(&dc);
2558: init_sar_tracker(&dc);
2559: reset_used_window(&dc);
1.1.1.2 ! root 2560: if (dc.icount) {
! 2561: dc.next_icount = tcg_temp_local_new_i32();
! 2562: }
1.1 root 2563:
2564: gen_icount_start();
2565:
2566: if (env->singlestep_enabled && env->exception_taken) {
2567: env->exception_taken = 0;
2568: tcg_gen_movi_i32(cpu_pc, dc.pc);
2569: gen_exception(&dc, EXCP_DEBUG);
2570: }
2571:
2572: do {
2573: check_breakpoint(env, &dc);
2574:
2575: if (search_pc) {
2576: j = gen_opc_ptr - gen_opc_buf;
2577: if (lj < j) {
2578: lj++;
2579: while (lj < j) {
2580: gen_opc_instr_start[lj++] = 0;
2581: }
2582: }
2583: gen_opc_pc[lj] = dc.pc;
2584: gen_opc_instr_start[lj] = 1;
2585: gen_opc_icount[lj] = insn_count;
2586: }
2587:
2588: if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
2589: tcg_gen_debug_insn_start(dc.pc);
2590: }
2591:
2592: ++dc.ccount_delta;
2593:
2594: if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
2595: gen_io_start();
2596: }
2597:
1.1.1.2 ! root 2598: if (dc.icount) {
! 2599: int label = gen_new_label();
! 2600:
! 2601: tcg_gen_addi_i32(dc.next_icount, cpu_SR[ICOUNT], 1);
! 2602: tcg_gen_brcondi_i32(TCG_COND_NE, dc.next_icount, 0, label);
! 2603: tcg_gen_mov_i32(dc.next_icount, cpu_SR[ICOUNT]);
! 2604: if (dc.debug) {
! 2605: gen_debug_exception(&dc, DEBUGCAUSE_IC);
! 2606: }
! 2607: gen_set_label(label);
! 2608: }
! 2609:
! 2610: if (dc.debug) {
! 2611: gen_ibreak_check(env, &dc);
! 2612: }
! 2613:
1.1 root 2614: disas_xtensa_insn(&dc);
2615: ++insn_count;
1.1.1.2 ! root 2616: if (dc.icount) {
! 2617: tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
! 2618: }
1.1 root 2619: if (env->singlestep_enabled) {
2620: tcg_gen_movi_i32(cpu_pc, dc.pc);
2621: gen_exception(&dc, EXCP_DEBUG);
2622: break;
2623: }
2624: } while (dc.is_jmp == DISAS_NEXT &&
2625: insn_count < max_insns &&
2626: dc.pc < next_page_start &&
2627: gen_opc_ptr < gen_opc_end);
2628:
2629: reset_litbase(&dc);
2630: reset_sar_tracker(&dc);
1.1.1.2 ! root 2631: if (dc.icount) {
! 2632: tcg_temp_free(dc.next_icount);
! 2633: }
1.1 root 2634:
2635: if (tb->cflags & CF_LAST_IO) {
2636: gen_io_end();
2637: }
2638:
2639: if (dc.is_jmp == DISAS_NEXT) {
2640: gen_jumpi(&dc, dc.pc, 0);
2641: }
2642: gen_icount_end(tb, insn_count);
2643: *gen_opc_ptr = INDEX_op_end;
2644:
2645: if (!search_pc) {
2646: tb->size = dc.pc - pc_start;
2647: tb->icount = insn_count;
2648: }
2649: }
2650:
1.1.1.2 ! root 2651: void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
1.1 root 2652: {
2653: gen_intermediate_code_internal(env, tb, 0);
2654: }
2655:
1.1.1.2 ! root 2656: void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb)
1.1 root 2657: {
2658: gen_intermediate_code_internal(env, tb, 1);
2659: }
2660:
1.1.1.2 ! root 2661: void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
1.1 root 2662: int flags)
2663: {
2664: int i, j;
2665:
2666: cpu_fprintf(f, "PC=%08x\n\n", env->pc);
2667:
2668: for (i = j = 0; i < 256; ++i) {
2669: if (sregnames[i]) {
2670: cpu_fprintf(f, "%s=%08x%c", sregnames[i], env->sregs[i],
2671: (j++ % 4) == 3 ? '\n' : ' ');
2672: }
2673: }
2674:
2675: cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
2676:
2677: for (i = j = 0; i < 256; ++i) {
2678: if (uregnames[i]) {
2679: cpu_fprintf(f, "%s=%08x%c", uregnames[i], env->uregs[i],
2680: (j++ % 4) == 3 ? '\n' : ' ');
2681: }
2682: }
2683:
2684: cpu_fprintf(f, (j % 4) == 0 ? "\n" : "\n\n");
2685:
2686: for (i = 0; i < 16; ++i) {
2687: cpu_fprintf(f, "A%02d=%08x%c", i, env->regs[i],
2688: (i % 4) == 3 ? '\n' : ' ');
2689: }
2690:
2691: cpu_fprintf(f, "\n");
2692:
2693: for (i = 0; i < env->config->nareg; ++i) {
2694: cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i],
2695: (i % 4) == 3 ? '\n' : ' ');
2696: }
2697: }
2698:
1.1.1.2 ! root 2699: void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
1.1 root 2700: {
2701: env->pc = gen_opc_pc[pc_pos];
2702: }
unix.superglobalmegacorp.com