aboutsummaryrefslogtreecommitdiff
path: root/target-xtensa/translate.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2011-09-06 03:55:45 +0400
committerBlue Swirl <blauwirbel@gmail.com>2011-09-10 16:57:39 +0000
commit6ad6dbf7916c59b6ae6dfe208dd64e0bf89dbf0a (patch)
tree29d3895812cc52290289631b5ec2fa8059d25992 /target-xtensa/translate.c
parent797d780b1375b1af1d7713685589bfdec9908dc3 (diff)
target-xtensa: implement extended L32R
See ISA, 4.3.3 for details. TB flag XTENSA_TBFLAG_LITBASE is used to track enable bit of LITBASE SR. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-xtensa/translate.c')
-rw-r--r--target-xtensa/translate.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 8f4500750c..07a737a90c 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -49,6 +49,7 @@ typedef struct DisasContext {
int ring;
uint32_t lbeg;
uint32_t lend;
+ TCGv_i32 litbase;
int is_jmp;
int singlestep_enabled;
@@ -71,6 +72,7 @@ static const char * const sregnames[256] = {
[LEND] = "LEND",
[LCOUNT] = "LCOUNT",
[SAR] = "SAR",
+ [LITBASE] = "LITBASE",
[SCOMPARE1] = "SCOMPARE1",
[WINDOW_BASE] = "WINDOW_BASE",
[WINDOW_START] = "WINDOW_START",
@@ -132,6 +134,21 @@ static inline bool option_enabled(DisasContext *dc, int opt)
return xtensa_option_enabled(dc->config, opt);
}
+static void init_litbase(DisasContext *dc)
+{
+ if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
+ dc->litbase = tcg_temp_local_new_i32();
+ tcg_gen_andi_i32(dc->litbase, cpu_SR[LITBASE], 0xfffff000);
+ }
+}
+
+static void reset_litbase(DisasContext *dc)
+{
+ if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
+ tcg_temp_free(dc->litbase);
+ }
+}
+
static void init_sar_tracker(DisasContext *dc)
{
dc->sar_5bit = false;
@@ -332,6 +349,13 @@ static void gen_wsr_sar(DisasContext *dc, uint32_t sr, TCGv_i32 s)
dc->sar_m32_5bit = false;
}
+static void gen_wsr_litbase(DisasContext *dc, uint32_t sr, TCGv_i32 s)
+{
+ tcg_gen_andi_i32(cpu_SR[sr], s, 0xfffff001);
+ /* This can change tb->flags, so exit tb */
+ gen_jumpi_check_loop_end(dc, -1);
+}
+
static void gen_wsr_windowbase(DisasContext *dc, uint32_t sr, TCGv_i32 v)
{
gen_helper_wsr_windowbase(v);
@@ -357,6 +381,7 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
[LBEG] = gen_wsr_lbeg,
[LEND] = gen_wsr_lend,
[SAR] = gen_wsr_sar,
+ [LITBASE] = gen_wsr_litbase,
[WINDOW_BASE] = gen_wsr_windowbase,
[PS] = gen_wsr_ps,
};
@@ -1298,11 +1323,13 @@ static void disas_xtensa_insn(DisasContext *dc)
case 1: /*L32R*/
{
TCGv_i32 tmp = tcg_const_i32(
- (0xfffc0000 | (RI16_IMM16 << 2)) +
- ((dc->pc + 3) & ~3));
-
- /* no ext L32R */
+ ((dc->tb->flags & XTENSA_TBFLAG_LITBASE) ?
+ 0 : ((dc->pc + 3) & ~3)) +
+ (0xfffc0000 | (RI16_IMM16 << 2)));
+ if (dc->tb->flags & XTENSA_TBFLAG_LITBASE) {
+ tcg_gen_add_i32(tmp, tmp, dc->litbase);
+ }
tcg_gen_qemu_ld32u(cpu_R[RRR_T], tmp, dc->cring);
tcg_temp_free(tmp);
}
@@ -1834,6 +1861,7 @@ static void gen_intermediate_code_internal(
dc.lend = env->sregs[LEND];
dc.is_jmp = DISAS_NEXT;
+ init_litbase(&dc);
init_sar_tracker(&dc);
gen_icount_start();
@@ -1876,6 +1904,7 @@ static void gen_intermediate_code_internal(
dc.pc < next_page_start &&
gen_opc_ptr < gen_opc_end);
+ reset_litbase(&dc);
reset_sar_tracker(&dc);
if (dc.is_jmp == DISAS_NEXT) {