203 |
203 |
tcg_temp_free(tcause);
|
204 |
204 |
}
|
205 |
205 |
|
|
206 |
static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
|
|
207 |
TCGv_i32 vaddr)
|
|
208 |
{
|
|
209 |
TCGv_i32 tpc = tcg_const_i32(dc->pc);
|
|
210 |
TCGv_i32 tcause = tcg_const_i32(cause);
|
|
211 |
gen_helper_exception_cause_vaddr(tpc, tcause, vaddr);
|
|
212 |
tcg_temp_free(tpc);
|
|
213 |
tcg_temp_free(tcause);
|
|
214 |
}
|
|
215 |
|
206 |
216 |
static void gen_check_privilege(DisasContext *dc)
|
207 |
217 |
{
|
208 |
218 |
if (dc->cring) {
|
... | ... | |
397 |
407 |
}
|
398 |
408 |
}
|
399 |
409 |
|
|
410 |
static void gen_load_store_alignment(DisasContext *dc, int shift,
|
|
411 |
TCGv_i32 addr, bool no_hw_alignment)
|
|
412 |
{
|
|
413 |
if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
|
|
414 |
tcg_gen_andi_i32(addr, addr, ~0 << shift);
|
|
415 |
} else if (option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT) &&
|
|
416 |
no_hw_alignment) {
|
|
417 |
int label = gen_new_label();
|
|
418 |
TCGv_i32 tmp = tcg_temp_new_i32();
|
|
419 |
tcg_gen_andi_i32(tmp, addr, ~(~0 << shift));
|
|
420 |
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
|
|
421 |
gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
|
|
422 |
gen_set_label(label);
|
|
423 |
tcg_temp_free(tmp);
|
|
424 |
}
|
|
425 |
}
|
|
426 |
|
400 |
427 |
static void disas_xtensa_insn(DisasContext *dc)
|
401 |
428 |
{
|
402 |
429 |
#define HAS_OPTION(opt) do { \
|
... | ... | |
1339 |
1366 |
#define gen_load_store(type, shift) do { \
|
1340 |
1367 |
TCGv_i32 addr = tcg_temp_new_i32(); \
|
1341 |
1368 |
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << shift); \
|
|
1369 |
if (shift) { \
|
|
1370 |
gen_load_store_alignment(dc, shift, addr, false); \
|
|
1371 |
} \
|
1342 |
1372 |
tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
|
1343 |
1373 |
tcg_temp_free(addr); \
|
1344 |
1374 |
} while (0)
|
... | ... | |
1468 |
1498 |
case 9: /*L16SI*/
|
1469 |
1499 |
gen_load_store(ld16s, 1);
|
1470 |
1500 |
break;
|
|
1501 |
#undef gen_load_store
|
1471 |
1502 |
|
1472 |
1503 |
case 10: /*MOVI*/
|
1473 |
1504 |
tcg_gen_movi_i32(cpu_R[RRI8_T],
|
... | ... | |
1475 |
1506 |
((RRI8_S & 0x8) ? 0xfffff000 : 0));
|
1476 |
1507 |
break;
|
1477 |
1508 |
|
|
1509 |
#define gen_load_store_no_hw_align(type) do { \
|
|
1510 |
TCGv_i32 addr = tcg_temp_local_new_i32(); \
|
|
1511 |
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2); \
|
|
1512 |
gen_load_store_alignment(dc, 2, addr, true); \
|
|
1513 |
tcg_gen_qemu_##type(cpu_R[RRI8_T], addr, dc->cring); \
|
|
1514 |
tcg_temp_free(addr); \
|
|
1515 |
} while (0)
|
|
1516 |
|
1478 |
1517 |
case 11: /*L32AIy*/
|
1479 |
1518 |
HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
|
1480 |
|
gen_load_store(ld32u, 2); /*TODO acquire?*/
|
|
1519 |
gen_load_store_no_hw_align(ld32u); /*TODO acquire?*/
|
1481 |
1520 |
break;
|
1482 |
1521 |
|
1483 |
1522 |
case 12: /*ADDI*/
|
... | ... | |
1497 |
1536 |
|
1498 |
1537 |
tcg_gen_mov_i32(tmp, cpu_R[RRI8_T]);
|
1499 |
1538 |
tcg_gen_addi_i32(addr, cpu_R[RRI8_S], RRI8_IMM8 << 2);
|
|
1539 |
gen_load_store_alignment(dc, 2, addr, true);
|
1500 |
1540 |
tcg_gen_qemu_ld32u(cpu_R[RRI8_T], addr, dc->cring);
|
1501 |
1541 |
tcg_gen_brcond_i32(TCG_COND_NE, cpu_R[RRI8_T],
|
1502 |
1542 |
cpu_SR[SCOMPARE1], label);
|
... | ... | |
1511 |
1551 |
|
1512 |
1552 |
case 15: /*S32RIy*/
|
1513 |
1553 |
HAS_OPTION(XTENSA_OPTION_MP_SYNCHRO);
|
1514 |
|
gen_load_store(st32, 2); /*TODO release?*/
|
|
1554 |
gen_load_store_no_hw_align(st32); /*TODO release?*/
|
1515 |
1555 |
break;
|
|
1556 |
#undef gen_load_store_no_hw_align
|
1516 |
1557 |
|
1517 |
1558 |
default: /*reserved*/
|
1518 |
1559 |
RESERVED();
|
1519 |
1560 |
break;
|
1520 |
1561 |
}
|
1521 |
1562 |
break;
|
1522 |
|
#undef gen_load_store
|
1523 |
1563 |
|
1524 |
1564 |
case 3: /*LSCIp*/
|
1525 |
1565 |
HAS_OPTION(XTENSA_OPTION_COPROCESSOR);
|
... | ... | |
1725 |
1765 |
#define gen_narrow_load_store(type) do { \
|
1726 |
1766 |
TCGv_i32 addr = tcg_temp_new_i32(); \
|
1727 |
1767 |
tcg_gen_addi_i32(addr, cpu_R[RRRN_S], RRRN_R << 2); \
|
|
1768 |
gen_load_store_alignment(dc, 2, addr, false); \
|
1728 |
1769 |
tcg_gen_qemu_##type(cpu_R[RRRN_T], addr, dc->cring); \
|
1729 |
1770 |
tcg_temp_free(addr); \
|
1730 |
1771 |
} while (0)
|