diff --git a/hw/tricore/tricore_testboard.c b/hw/tricore/tricore_testboard.c index e35ad1e19462..46a3f9f3ca25 100644 --- a/hw/tricore/tricore_testboard.c +++ b/hw/tricore/tricore_testboard.c @@ -22,6 +22,7 @@ #include "qemu/units.h" #include "qapi/error.h" #include "cpu.h" +#include "disas/disas.h" #include "net/net.h" #include "hw/boards.h" #include "hw/loader.h" @@ -33,6 +34,63 @@ /* Board init. */ +/* +static int symfind(const void *s0, const void *s1) +{ + target_ulong addr = *(target_ulong *)s0; + struct elf_sym *sym = (struct elf_sym *)s1; + int result = 0; + if (addr < sym->st_value) { + result = -1; + } else if (addr >= sym->st_value + sym->st_size) { + result = 1; + } + return result; +} +*/ +//static int addrfind(const void *s0, const void *s1) +//{ +// const char *symname = (const char *)s0; +// struct elf_sym *sym = (struct elf_sym *)s1; +// int result = 1; +// if (strcmp(s->disas_strtab + sym->st_name,symname)==0) result=0; +// return result; +//} + +static uint32_t lookup_addrxx(const char *symbol) +{ + + struct syminfo *s; + /* binary search */ + int i; + for (s = syminfos; s; s = s->next) + { + struct elf32_sym *syms = s->disas_symtab.elf32; + for (i=0; idisas_num_syms; i+=1) + { + if (strcmp(s->disas_strtab + syms[i].st_name,symbol)==0) return syms[i].st_value; + } + } + return 0; +} + +//const char *lookup_symbol(target_ulong orig_addr) +//{ +// const char *symbol = ""; +// struct syminfo *s; +// +// for (s = syminfos; s; s = s->next) { +// symbol = s->lookup_symbol(s, orig_addr); +// if (symbol[0] != '\0') { +// break; +// } +// } +// +// return symbol; +//} + + + static struct tricore_boot_info tricoretb_binfo; static void tricore_load_kernel(CPUTriCoreState *env) @@ -50,7 +108,8 @@ static void tricore_load_kernel(CPUTriCoreState *env) exit(1); } env->PC = entry; - + env->main_addr_entry=lookup_addrxx("main"); + env->kernel_filename=tricoretb_binfo.kernel_filename; } static void tricore_testboard_init(MachineState *machine, int board_id) diff --git a/semihosting/config.c b/semihosting/config.c index 137171b717b2..2ff32f1d63ff 100644 --- a/semihosting/config.c +++ b/semihosting/config.c @@ -111,7 +111,8 @@ void semihosting_arg_fallback(const char *file, const char *cmd) char *cmd_token; /* argv[0] */ - add_semihosting_arg(&semihosting, "arg", file, NULL); +// removed it, arg_fallback and standard is behaving different in terms of file name for first arg +// add_semihosting_arg(&semihosting, "arg", file, NULL); /* split -append and initialize argv[1..n] */ cmd_token = strtok(g_strdup(cmd), " "); diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h index dcdbbff4ba9c..dc04eef625ba 100644 --- a/target/tricore/cpu.h +++ b/target/tricore/cpu.h @@ -194,6 +194,10 @@ struct CPUTriCoreState { const tricore_def_t *cpu_model; void *irq[8]; struct QEMUTimer *timer; /* Internal timer */ + uint32_t main_addr_entry; + uint32_t main_addr_next; + uint32_t main_sp_correction; + const char *kernel_filename; }; /** diff --git a/target/tricore/translate.c b/target/tricore/translate.c index e1ca56472d81..714721547f46 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -34,6 +34,7 @@ #include "tricore-opcodes.h" #include "exec/translator.h" #include "exec/log.h" +#include "elf.h" /* * TCG registers @@ -9029,94 +9030,212 @@ static bool insn_crosses_page(CPUTriCoreState *env, DisasContext *ctx) return !tricore_insn_is_16bit(insn); } - +#define _D(x) +//#define _D(x) x static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) { - DisasContext *ctx = container_of(dcbase, DisasContext, base); - CPUTriCoreState *env = cpu->env_ptr; - uint16_t insn_lo; - bool is_16bit; - - insn_lo = cpu_lduw_code(env, ctx->base.pc_next); - is_16bit = tricore_insn_is_16bit(insn_lo); - if (is_16bit) { - ctx->opcode = insn_lo; - ctx->pc_succ_insn = ctx->base.pc_next + 2; - decode_16Bit_opc(ctx); - if (insn_lo==INSNOPCODE_DEBUG16) - { - //TODO has to be done - //if the debug is the first insn of the context everything is - //if a later one (no singlestep mode), terminate the disasscontext - //observed in exit where A14 is update in the prev. instruction - //in virtio this should not be the case becaue is always jumped - //tcg_gen_movi_tl(cpu_monitor, 0xAAAA); - - /* It is debug16 instruction, the following cases are possible (maybe to be extended) + DisasContext *ctx = container_of(dcbase, DisasContext, base); + CPUTriCoreState *env = cpu->env_ptr; + uint16_t insn_lo; + bool is_16bit; + + if (semihosting_enabled() && !gdb_state()) + { + /* parameter passing via commandline to qemu */ + /* e.g. --semihosting-config enable=on,arg=xxxx1234,arg=yyyy5678 */ + if (ctx->base.pc_next==env->main_addr_entry) + { + _D (fprintf(stderr,"Main(...) reached PC=%8.8x\n",env->main_addr_entry)); + _D (fprintf(stderr,"Main got %d arguments\n",semihosting_get_argc())); + { + int i; + _D (fprintf(stderr,"arg[%d]=%s\n",0,env->kernel_filename)); + for (i=0; iPCXI); + // cpu_ldl_data + /* extend by one byte */ + uint32_t sp; + uint32_t sp_adder; + uint32_t sp_adder_argv; + uint32_t sp_adder_params; + uint32_t ii,jj; + sp_adder=0; + sp_adder_argv=0; + sp_adder+=(semihosting_get_argc()+1)<<2; + sp_adder_params=sp_adder; + if (env->kernel_filename!=NULL) sp_adder+=strlen(env->kernel_filename)+1; + for (ii=0; iigpr_a[10],env->gpr_a[4],sp_adder)); + + env->gpr_a[10]=env->gpr_a[10]-sp_adder; + env->gpr_a[4]=env->gpr_a[4]-sp_adder; + sp=env->gpr_a[10]; + env->gpr_d[4]=semihosting_get_argc()+1; + //fill in the pointer and string + if (env->kernel_filename==NULL) + { + cpu_stl_data(env, sp+sp_adder_argv, 0); //argv + sp_adder_argv+=4; + } + else + { + cpu_stl_data(env, sp+sp_adder_argv, sp+sp_adder_params); + sp_adder_argv+=4; + for (ii=0; ii<=strlen(env->kernel_filename); ii+=1) + { + cpu_stb_data(env, sp+sp_adder_params,env->kernel_filename[ii]); + sp_adder_params+=1; + } + } + //fill in *argv + for (jj=0; jjmain_sp_correction=sp_adder; + //a11 give the address where main is returnign too + env->main_addr_next=env->gpr_a[11]; + } + if (ctx->base.pc_next==env->main_addr_next) + { + //reverse sp + //a4 is anyhow destroyed + _D (fprintf(stderr,"After call of Main(...) reached PC=%8.8x\n",env->main_addr_next)); + env->gpr_a[10]=env->gpr_a[10]+env->main_sp_correction; + } + } + + insn_lo = cpu_lduw_code(env, ctx->base.pc_next); + is_16bit = tricore_insn_is_16bit(insn_lo); + if (is_16bit) { + ctx->opcode = insn_lo; + ctx->pc_succ_insn = ctx->base.pc_next + 2; + decode_16Bit_opc(ctx); + if (insn_lo==INSNOPCODE_DEBUG16) + { + //TODO has to be done + //if the debug is the first insn of the context everything is + //if a later one (no singlestep mode), terminate the disasscontext + //observed in exit where A14 is update in the prev. instruction + //in virtio this should not be the case becaue is always jumped + //tcg_gen_movi_tl(cpu_monitor, 0xAAAA); + + /* It is debug16 instruction, the following cases are possible (maybe to be extended) 1) if a debugger is not connected take debug as nop 2) if a debugger is connected do a debug exception, virtio/semihosting can be done by client (hook or remoteprotocoll) 3) if a debugger is connected handle virtio/semihsoting and generate debug exceptions for other cases 4) if a debugger is not connected, do virtio/semihosting and exit in other cases - */ - uint32_t markerpcm2; - uint32_t markerpcm4; - markerpcm2=cpu_lduw_code(env, ctx->base.pc_next-2); - markerpcm4=cpu_lduw_code(env, ctx->base.pc_next-4); - - qemu_log_mask(LOG_GUEST_ERROR,"debug16 gdb=%d semihost=%d pc=%8.8x mp2m=%4.4x mp4m=%4.4x\n",semihosting_enabled(),gdb_state(),ctx->base.pc_next,markerpcm2,markerpcm4); - //if the debug16 insn has an exit marker we push in each case an exit exception - if ((markerpcm2 & GCC_VIRTIO_MARKEREXITPCM2_MASK) ==GCC_VIRTIO_MARKEREXITPCM2) - { - //Register A14 contains the return value - //0x900d is considered as 0, else pass as exit argument - //exit markers in trap functions have on identifiers and can generate additional infos - qemu_log_mask(LOG_GUEST_ERROR,"Exit Marker\n"); - generate_qemu_excp(ctx, EXCP_EXIT); - ctx->base.is_jmp = DISAS_TOO_MANY; - } - else if (gdb_state()) - { - qemu_log_mask(LOG_GUEST_ERROR,"Debug with GDB, no semi\n"); - generate_qemu_excp(ctx, EXCP_DEBUG); - ctx->base.is_jmp = DISAS_TOO_MANY; - } - else if (semihosting_enabled()) - { - qemu_log_mask(LOG_GUEST_ERROR,"Debug no GDB but with semi\n"); - if ((markerpcm2==GCC_VIRTIO_MARKERPCM2) && (markerpcm4==GCC_VIRTIO_MARKERPCM4)) - { - //Register D12 contains the id - cpu->halted = 1; - cpu->exception_index = EXCP_SEMIHOST; - cpu_loop_exit(cpu); - ctx->base.is_jmp = DISAS_TOO_MANY; - } - } - else - { - qemu_log_mask(LOG_GUEST_ERROR,"Debug as nop\n"); - //do nothing just take it as nop - } - } - } else { - uint32_t insn_hi = cpu_lduw_code(env, ctx->base.pc_next + 2); - ctx->opcode = insn_hi << 16 | insn_lo; - ctx->pc_succ_insn = ctx->base.pc_next + 4; - decode_32Bit_opc(ctx); - } - ctx->base.pc_next = ctx->pc_succ_insn; - - if (ctx->base.is_jmp == DISAS_NEXT) { - target_ulong page_start; - - page_start = ctx->base.pc_first & TARGET_PAGE_MASK; - if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - || (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - 3 - && insn_crosses_page(env, ctx))) { - ctx->base.is_jmp = DISAS_TOO_MANY; - } - } + */ + uint32_t markerpcm2; + uint32_t markerpcm4; + markerpcm2=cpu_lduw_code(env, ctx->base.pc_next-2); + markerpcm4=cpu_lduw_code(env, ctx->base.pc_next-4); + + qemu_log_mask(LOG_GUEST_ERROR,"debug16 gdb=%d semihost=%d pc=%8.8x mp2m=%4.4x mp4m=%4.4x\n",semihosting_enabled(),gdb_state(),ctx->base.pc_next,markerpcm2,markerpcm4); + //if the debug16 insn has an exit marker we push in each case an exit exception + if ((markerpcm2 & GCC_VIRTIO_MARKEREXITPCM2_MASK) ==GCC_VIRTIO_MARKEREXITPCM2) + { + //Register A14 contains the return value + //0x900d is considered as 0, else pass as exit argument + //exit markers in trap functions have on identifiers and can generate additional infos + qemu_log_mask(LOG_GUEST_ERROR,"Exit Marker\n"); + generate_qemu_excp(ctx, EXCP_EXIT); + ctx->base.is_jmp = DISAS_TOO_MANY; + } + else if (gdb_state()) + { + qemu_log_mask(LOG_GUEST_ERROR,"Debug with GDB, no semi\n"); + generate_qemu_excp(ctx, EXCP_DEBUG); + ctx->base.is_jmp = DISAS_TOO_MANY; + } + else if (semihosting_enabled()) + { + qemu_log_mask(LOG_GUEST_ERROR,"Debug no GDB but with semi\n"); + if ((markerpcm2==GCC_VIRTIO_MARKERPCM2) && (markerpcm4==GCC_VIRTIO_MARKERPCM4)) + { + //Register D12 contains the id + cpu->halted = 1; + cpu->exception_index = EXCP_SEMIHOST; + cpu_loop_exit(cpu); + ctx->base.is_jmp = DISAS_TOO_MANY; + } + } + else + { + qemu_log_mask(LOG_GUEST_ERROR,"Debug as nop\n"); + //do nothing just take it as nop + } + } + } else { + uint32_t insn_hi = cpu_lduw_code(env, ctx->base.pc_next + 2); + ctx->opcode = insn_hi << 16 | insn_lo; + ctx->pc_succ_insn = ctx->base.pc_next + 4; + decode_32Bit_opc(ctx); + } + ctx->base.pc_next = ctx->pc_succ_insn; + + if (ctx->base.is_jmp == DISAS_NEXT) { + target_ulong page_start; + + page_start = ctx->base.pc_first & TARGET_PAGE_MASK; + if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE + || (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - 3 + && insn_crosses_page(env, ctx))) { + ctx->base.is_jmp = DISAS_TOO_MANY; + } + } } static void tricore_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) @@ -9173,6 +9292,9 @@ void cpu_state_reset(CPUTriCoreState *env) /* Reset Regs to Default Value */ env->PSW = 0xb80; env->semihost=0; + env->main_addr_entry=0; + env->main_addr_next=0; + env->kernel_filename=NULL; fpu_set_state(env); } diff --git a/target/tricore/tricore-semi.c b/target/tricore/tricore-semi.c index 8f32bbb7a037..b134984f87a2 100644 --- a/target/tricore/tricore-semi.c +++ b/target/tricore/tricore-semi.c @@ -575,7 +575,7 @@ static void tricore_vio_read (CPUState *cs) goto done; } - if (target_write_memory (cs,rem_buf, buf, rlen)) + if (target_write_memory (cs,rem_buf, buf, rlen)) { tricore_vio_set_result (cs,-1, EIO); goto done;