diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2011-09-06 03:55:41 +0400 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2011-09-10 16:57:38 +0000 |
commit | 40643d7c0fe4dc967ebc2f75e6758a4649776949 (patch) | |
tree | 6fae13c6f2190389f1c0c78288f3037dc0d65d26 /target-xtensa/translate.c | |
parent | f0a548b93da07b6546e4f8178a93c47284a27d05 (diff) |
target-xtensa: implement exceptions
- mark privileged opcodes with ring check;
- make debug exception on exception handler entry.
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.c | 107 |
1 files changed, 102 insertions, 5 deletions
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index 32fab09e48..dccd453512 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -67,7 +67,12 @@ static TCGv_i32 cpu_UR[256]; static const char * const sregnames[256] = { [SAR] = "SAR", [SCOMPARE1] = "SCOMPARE1", + [EPC1] = "EPC1", + [DEPC] = "DEPC", + [EXCSAVE1] = "EXCSAVE1", [PS] = "PS", + [EXCCAUSE] = "EXCCAUSE", + [EXCVADDR] = "EXCVADDR", }; static const char * const uregnames[256] = { @@ -165,6 +170,22 @@ static void gen_exception(int excp) tcg_temp_free(tmp); } +static void gen_exception_cause(DisasContext *dc, uint32_t cause) +{ + TCGv_i32 tpc = tcg_const_i32(dc->pc); + TCGv_i32 tcause = tcg_const_i32(cause); + gen_helper_exception_cause(tpc, tcause); + tcg_temp_free(tpc); + tcg_temp_free(tcause); +} + +static void gen_check_privilege(DisasContext *dc) +{ + if (dc->cring) { + gen_exception_cause(dc, PRIVILEGED_CAUSE); + } +} + static void gen_jump_slot(DisasContext *dc, TCGv dest, int slot) { tcg_gen_mov_i32(cpu_pc, dest); @@ -392,7 +413,7 @@ static void disas_xtensa_insn(DisasContext *dc) case 0: /*SNM0*/ switch (CALLX_M) { case 0: /*ILL*/ - TBD(); + gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); break; case 1: /*reserved*/ @@ -479,7 +500,52 @@ static void disas_xtensa_insn(DisasContext *dc) break; case 3: /*RFEIx*/ - TBD(); + switch (RRR_T) { + case 0: /*RFETx*/ + HAS_OPTION(XTENSA_OPTION_EXCEPTION); + switch (RRR_S) { + case 0: /*RFEx*/ + gen_check_privilege(dc); + tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], ~PS_EXCM); + gen_jump(dc, cpu_SR[EPC1]); + break; + + case 1: /*RFUEx*/ + RESERVED(); + break; + + case 2: /*RFDEx*/ + gen_check_privilege(dc); + gen_jump(dc, cpu_SR[ + dc->config->ndepc ? DEPC : EPC1]); + break; + + case 4: /*RFWOw*/ + case 5: /*RFWUw*/ + HAS_OPTION(XTENSA_OPTION_WINDOWED_REGISTER); + TBD(); + break; + + default: /*reserved*/ + RESERVED(); + break; + } + break; + + case 1: /*RFIx*/ + HAS_OPTION(XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT); + TBD(); + break; + + case 2: /*RFME*/ + TBD(); + break; + + default: /*reserved*/ + RESERVED(); + break; + + } break; case 4: /*BREAKx*/ @@ -489,12 +555,28 @@ static void disas_xtensa_insn(DisasContext *dc) case 5: /*SYSCALLx*/ HAS_OPTION(XTENSA_OPTION_EXCEPTION); - TBD(); + switch (RRR_S) { + case 0: /*SYSCALLx*/ + gen_exception_cause(dc, SYSCALL_CAUSE); + break; + + case 1: /*SIMCALL*/ + TBD(); + break; + + default: + RESERVED(); + break; + } break; case 6: /*RSILx*/ HAS_OPTION(XTENSA_OPTION_INTERRUPT); - TBD(); + gen_check_privilege(dc); + tcg_gen_mov_i32(cpu_R[RRR_T], cpu_SR[PS]); + tcg_gen_ori_i32(cpu_SR[PS], cpu_SR[PS], RRR_S); + tcg_gen_andi_i32(cpu_SR[PS], cpu_SR[PS], + RRR_S | ~PS_INTLEVEL); break; case 7: /*WAITIx*/ @@ -691,6 +773,9 @@ static void disas_xtensa_insn(DisasContext *dc) case 6: /*XSR*/ { TCGv_i32 tmp = tcg_temp_new_i32(); + if (RSR_SR >= 64) { + gen_check_privilege(dc); + } tcg_gen_mov_i32(tmp, cpu_R[RRR_T]); gen_rsr(dc, cpu_R[RRR_T], RSR_SR); gen_wsr(dc, RSR_SR, tmp); @@ -799,6 +884,9 @@ static void disas_xtensa_insn(DisasContext *dc) case 3: /*RST3*/ switch (OP2) { case 0: /*RSR*/ + if (RSR_SR >= 64) { + gen_check_privilege(dc); + } gen_rsr(dc, cpu_R[RRR_T], RSR_SR); if (!sregnames[RSR_SR]) { TBD(); @@ -806,6 +894,9 @@ static void disas_xtensa_insn(DisasContext *dc) break; case 1: /*WSR*/ + if (RSR_SR >= 64) { + gen_check_privilege(dc); + } gen_wsr(dc, RSR_SR, cpu_R[RRR_T]); if (!sregnames[RSR_SR]) { TBD(); @@ -1421,7 +1512,7 @@ static void disas_xtensa_insn(DisasContext *dc) break; case 6: /*ILL.Nn*/ - TBD(); + gen_exception_cause(dc, ILLEGAL_INSTRUCTION_CAUSE); break; default: /*reserved*/ @@ -1493,6 +1584,12 @@ static void gen_intermediate_code_internal( gen_icount_start(); + if (env->singlestep_enabled && env->exception_taken) { + env->exception_taken = 0; + tcg_gen_movi_i32(cpu_pc, dc.pc); + gen_exception(EXCP_DEBUG); + } + do { check_breakpoint(env, &dc); |