/* GX M32R implementation. Copyright (C) 1998 Cygnus Solutions. */ #include #include #include /* common simulator framework */ #include "sim-main.h" #include "sim-base.h" #include "sim-core.h" #include "sim-gx.h" #include "sim-assert.h" #include "targ-vals.h" /* internal functions */ void m32r_emit_long_insn(sim_gx_block* block, PCADDR pc, unsigned insn, int optimized); void m32r_emit_short_insn(sim_gx_block* block, PCADDR pc, unsigned insn, int optimized); /* callback functions */ unsigned m32r_gx_load(unsigned pc, unsigned addr); void m32r_gx_store(unsigned pc, unsigned addr, unsigned data); signed char m32r_gx_load1(unsigned pc, unsigned addr); void m32r_gx_store1(unsigned pc, unsigned addr, signed char data); signed short m32r_gx_load2(unsigned pc, unsigned addr); void m32r_gx_store2(unsigned pc, unsigned addr, signed short data); void m32r_gx_syscall(tgx_syscall_data* data); /* external functions */ void tgx_block_ctor(sim_gx_block* block, sim_cia cia) { /* pick translation boundaries */ unsigned_4 origin, length, divisor; #define GX_PAGE_SIZE 4096 origin = (cia / GX_PAGE_SIZE) * GX_PAGE_SIZE; length = GX_PAGE_SIZE; /* fill in general target-dependent fields */ divisor = 4; /* m32r instruction-pairs occur on word boundaries */ tgx_block_ctor2(block, origin, length, divisor); } void tgx_block_ctor2(sim_gx_block* block, unsigned_4 origin, unsigned_4 length, unsigned_4 divisor) { block->origin = origin; block->length = length; block->divisor = divisor; /* allocate pc_flags array */ block->pc_flags = zalloc(block->length / block->divisor); /* allocate tgx_callbacks */ block->callbacks = zalloc(sizeof(tgx_callbacks)); block->callbacks->load = m32r_gx_load; block->callbacks->store = m32r_gx_store; block->callbacks->load1 = m32r_gx_load1; block->callbacks->store1 = m32r_gx_store1; block->callbacks->load2 = m32r_gx_load2; block->callbacks->store2 = m32r_gx_store2; block->callbacks->syscall = m32r_gx_syscall; } void tgx_emit_pre_function(sim_gx_block* gx, int optimized) { sim_gx_compiled_block* block = optimized ? gx->optimized_block : gx->learning_block; ASSERT(block->source_file != NULL); fprintf(block->source_file, "\n"); fprintf(block->source_file, "#include \n"); fprintf(block->source_file, "\n"); fprintf(block->source_file, /* match with definition in sim-main.h! */ "typedef struct tgx_cpu_regs\n" "{\n" " unsigned int h_pc; /* program counter */\n" " signed int h_gr[16]; /* general registers */\n" " unsigned int h_cr[16]; /* control registers */\n" " long long h_accum; /* accumulator */\n" " unsigned h_lock; /* lock */\n" "} tgx_cpu_regs;\n"); fprintf(block->source_file, /* match with definition in sim-main.h! */ "typedef struct tgx_syscall_data\n" "{\n" " unsigned pc;\n" " unsigned func;\n" " unsigned arg1;\n" " unsigned arg2;\n" " unsigned arg3;\n" " unsigned errcode;\n" " unsigned result;\n" " unsigned result2;\n" "} tgx_syscall_data;\n"); fprintf(block->source_file, /* match with definition in sim-main.h! */ "typedef struct tgx_callbacks\n" "{\n" " unsigned (*load)(unsigned pc, unsigned addr);\n" " void (*store)(unsigned pc, unsigned addr, unsigned data);\n" " signed char (*load1)(unsigned pc, unsigned addr);\n" " void (*store1)(unsigned pc, unsigned addr, signed char data);\n" " signed short (*load2)(unsigned pc, unsigned addr);\n" " void (*store2)(unsigned pc, unsigned addr, signed short data);\n" " void (*syscall)(tgx_syscall_data* data);\n" "} tgx_callbacks;\n"); } void tgx_emit_load_block(sim_gx_block* gx, int optimized) { sim_gx_compiled_block* block = optimized ? gx->optimized_block : gx->learning_block; ASSERT(block->source_file != NULL); fprintf(block->source_file, /* match with definition above */ " unsigned int pc = regs->h_pc;\n" " unsigned int npc = pc;\n" " signed int temp;\n" " signed int gr0 = regs->h_gr[0], gr1 = regs->h_gr[1];\n" " signed int gr2 = regs->h_gr[2], gr3 = regs->h_gr[3];\n" " signed int gr4 = regs->h_gr[4], gr5 = regs->h_gr[5];\n" " signed int gr6 = regs->h_gr[6], gr7 = regs->h_gr[7];\n" " signed int gr8 = regs->h_gr[8], gr9 = regs->h_gr[9];\n" " signed int gr10 = regs->h_gr[10], gr11 = regs->h_gr[11];\n" " signed int gr12 = regs->h_gr[12], gr13 = regs->h_gr[13];\n" " signed int gr14 = regs->h_gr[14];\n" " unsigned int cr0 = regs->h_cr[0], cr1 = regs->h_cr[1];\n" " unsigned int cr2 = regs->h_cr[2], cr3 = regs->h_cr[3];\n" " unsigned int cr4 = regs->h_cr[4], cr5 = regs->h_cr[5];\n" " unsigned int cr6 = regs->h_cr[6], cr7 = regs->h_cr[7];\n" " unsigned int cr8 = regs->h_cr[8], cr9 = regs->h_cr[9];\n" " unsigned int cr10 = regs->h_cr[10], cr11 = regs->h_cr[11];\n" " unsigned int cr12 = regs->h_cr[12], cr13 = regs->h_cr[13];\n" " unsigned int cr14 = regs->h_cr[14], cr15 = regs->h_cr[15];\n" " long long accum = regs->h_accum;\n" " unsigned cond = cr0 & 0x01;\n" " unsigned sm = cr0 & 0x80;\n" " unsigned int gr15 = sm ? cr3 : cr2;\n" " unsigned lock = regs->h_lock;\n"); } sim_cia tgx_emit_insn(sim_gx_block* gx, sim_cia cia, int optimized) { PCADDR pc = cia; SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); USI insn = sim_core_read_unaligned_4 (cpu, NULL_CIA, exec_map, cia); USI insn1 = (insn >> 16) & 0xffff; USI insn2 = insn & 0xffff; sim_gx_compiled_block* block = optimized ? gx->optimized_block : gx->learning_block; ASSERT(block->source_file != NULL); /* classify instruction word */ if (insn & 0x80000000) /* single long word */ m32r_emit_long_insn(gx, pc, insn, optimized); else /* two sequential half words */ { /* translate first instruction */ m32r_emit_short_insn(gx, pc, insn1, optimized); if(insn2 & 0x8000) /* parallel? */ { fprintf(block->source_file, " /* || */\n"); insn2 &= 0x7fff; /* XXX: genuine parallelism handling */ } else fprintf(block->source_file, " /* -> */\n"); /* translate second instruction */ m32r_emit_short_insn(gx, pc + 2, insn2, optimized); } return cia + 4; /* next instruction pair */ } void tgx_emit_save_block(sim_gx_block* gx, int optimized) { sim_gx_compiled_block* block = optimized ? gx->optimized_block : gx->learning_block; ASSERT(block->source_file != NULL); fprintf(block->source_file, /* match with definition above */ " cr0 = (cr0 & 0x00c140) | (sm ? 0x80 : 0 ) | (cond ? 1 : 0);\n" " cr1 = cond ? 1 : 0;\n" " cr2 = sm ? cr2 : gr15;\n" " cr3 = sm ? gr15 : cr3;\n" " regs->h_pc = npc;\n" " regs->h_gr[0] = gr0, regs->h_gr[1] = gr1;\n" " regs->h_gr[2] = gr2, regs->h_gr[3] = gr3;\n" " regs->h_gr[4] = gr4, regs->h_gr[5] = gr5;\n" " regs->h_gr[6] = gr6, regs->h_gr[7] = gr7;\n" " regs->h_gr[8] = gr8, regs->h_gr[9] = gr9;\n" " regs->h_gr[10] = gr10, regs->h_gr[11] = gr11;\n" " regs->h_gr[12] = gr12, regs->h_gr[13] = gr13;\n" " regs->h_gr[14] = gr14, regs->h_gr[15] = gr15;\n" " regs->h_cr[0] = cr0, regs->h_cr[1] = cr1;\n" " regs->h_cr[2] = cr2, regs->h_cr[3] = cr3;\n" " regs->h_cr[4] = cr4, regs->h_cr[5] = cr5;\n" " regs->h_cr[6] = cr6, regs->h_cr[7] = cr7;\n" " regs->h_cr[8] = cr8, regs->h_cr[9] = cr9;\n" " regs->h_cr[10] = cr10, regs->h_cr[11] = cr11;\n" " regs->h_cr[12] = cr12, regs->h_cr[13] = cr13;\n" " regs->h_cr[14] = cr14, regs->h_cr[15] = cr15;\n" " regs->h_accum = accum;\n" " regs->h_lock = lock;\n"); } void tgx_emit_post_function(sim_gx_block* gx, int optimized) { sim_gx_compiled_block* block = optimized ? gx->optimized_block : gx->learning_block; ASSERT(block->source_file != NULL); fprintf(block->source_file, "\n/* end of file */\n"); } void tgx_block_dtor(sim_gx_block* block) { } int tgx_optimize_test(sim_gx_block* block) { unsigned_4 current_time = time(NULL); unsigned_4 constant_time = current_time - block->learn_last_change; int opt; /* try another optimize run if the system has settled down */ opt = (block->compile_time != 0 && block->learn_last_change != 0 && constant_time > block->compile_time); /* if(opt) printf("optimize_test: now: %d, chg: %d, comp: %d, count: %d => opt %d\n", current_time, block->learn_last_change, block->compile_time, block->opt_compile_count, opt); */ return opt; } unsigned m32r_gx_load(unsigned pc, unsigned addr) { SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); USI data = sim_core_read_unaligned_4 (cpu, pc, read_map, addr); return data; } void m32r_gx_store(unsigned pc, unsigned addr, unsigned data) { SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); sim_core_write_unaligned_4 (cpu, pc, write_map, addr, data); } signed char m32r_gx_load1(unsigned pc, unsigned addr) { SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); signed char data = sim_core_read_unaligned_1 (cpu, pc, read_map, addr); return data; } void m32r_gx_store1(unsigned pc, unsigned addr, signed char data) { SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); sim_core_write_unaligned_1 (cpu, pc, write_map, addr, data); } signed short m32r_gx_load2(unsigned pc, unsigned addr) { SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); signed short data = sim_core_read_unaligned_2 (cpu, pc, read_map, addr); return data; } void m32r_gx_store2(unsigned pc, unsigned addr, signed short data) { SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); sim_core_write_unaligned_2 (cpu, pc, write_map, addr, data); } static int syscall_read_mem (host_callback *cb, struct cb_syscall *sc, unsigned long taddr, char *buf, int bytes) { SIM_DESC sd = (SIM_DESC) sc->p1; SIM_CPU *cpu = (SIM_CPU *) sc->p2; return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes); } static int syscall_write_mem (host_callback *cb, struct cb_syscall *sc, unsigned long taddr, const char *buf, int bytes) { SIM_DESC sd = (SIM_DESC) sc->p1; SIM_CPU *cpu = (SIM_CPU *) sc->p2; return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes); } void m32r_gx_syscall(tgx_syscall_data* data) { SIM_DESC sd = CURRENT_STATE; sim_cpu* cpu = STATE_CPU (sd, 0); host_callback *cb = STATE_CALLBACK (sd); CB_SYSCALL s; CB_SYSCALL_INIT (&s); s.func = data->func; s.arg1 = data->arg1; s.arg2 = data->arg2; s.arg3 = data->arg3; if (s.func == TARGET_SYS_exit) { sim_engine_halt (sd, cpu, NULL, data->pc, sim_exited, s.arg1); exit(s.arg1); } s.p1 = (PTR) sd; s.p2 = (PTR) cpu; s.read_mem = syscall_read_mem; s.write_mem = syscall_write_mem; cb_syscall (cb, &s); data->errcode = s.errcode; data->result = s.result; data->result2 = s.result2; } void m32r_emit_long_insn(sim_gx_block* gx, PCADDR pc, unsigned insn, int optimized) { int op1 = (insn & 0xf0000000) >> 28; int r1 = (insn & 0x0f000000) >> 24; int op2 = (insn & 0x00f00000) >> 20; int r2 = (insn & 0x000f0000) >> 16; short lit2 = (insn & 0x0000ffff); int lit3 = (insn & 0x00ffffff); sim_gx_compiled_block* block = optimized ? gx->optimized_block : gx->learning_block; FILE* f = block->source_file; ASSERT(block->source_file != NULL); if(op1 == 0x8 && op2 == 0x4 && r1 == 0) { fprintf(f, " /* CMPI R%d,#%d */\n", r2, lit2); fprintf(f, " cond = (gr%d < %d);\n", r2, lit2); } else if(op1 == 0x8 && op2 == 0x5 && r1 == 0) { fprintf(f, " /* CMPUI R%d,#%d */\n", r2, lit2); fprintf(f, " cond = ((unsigned) gr%d < %u);\n", r2, (unsigned)((int) lit2)); } else if(op1 == 0x8 && op2 == 0x8) { fprintf(f, " /* ADDV3 R%d,R%d,#%d */\n", r1, r2, lit2); fprintf(f, " temp = gr%d + %d;\n", r2, lit2); fprintf(f, " cond = (~(gr%d & %d) & (gr%d ^ temp)) & (1<<31);\n", r2, lit2, r2); fprintf(f, " gr%d = temp;\n", r1); } else if(op1 == 0x8 && op2 == 0xa) { fprintf(f, " /* ADD3 R%d,R%d,#%d */\n", r1, r2, lit2); fprintf(f, " gr%d = gr%d + %d;\n", r1, r2, lit2); } else if(op1 == 0x8 && op2 == 0xc) { fprintf(f, " /* AND3 R%d,R%d,#%u */\n", r1, r2, (unsigned short) lit2); fprintf(f, " gr%d = gr%d & %u;\n", r1, r2, (unsigned short) lit2); } else if(op1 == 0x8 && op2 == 0xd) { fprintf(f, " /* XOR3 R%d,R%d,#%d */\n", r1, r2, lit2); fprintf(f, " gr%d = gr%d ^ %d;\n", r1, r2, lit2); } else if(op1 == 0x8 && op2 == 0xe) { fprintf(f, " /* OR3 R%d,R%d,#%u */\n", r1, r2, (unsigned short) lit2); fprintf(f, " gr%d = gr%d | %u;\n", r1, r2, (unsigned short) lit2); } else if(op1 == 0x9 && op2 == 0x0 && lit2 == 0) { fprintf(f, " /* DIV R%d,R%d */\n", r1, r2); fprintf(f, " if(gr%d != 0)\n", r2); fprintf(f, " gr%d = gr%d / gr%d;\n", r1, r1, r2); } else if(op1 == 0x9 && op2 == 0x1 && lit2 == 0) { fprintf(f, " /* DIVU R%d,R%d */\n", r1, r2); fprintf(f, " if(gr%d != 0)\n", r2); fprintf(f, " gr%d = (unsigned) gr%d / (unsigned) gr%d;\n", r1, r1, r2); } else if(op1 == 0x9 && op2 == 0x2 && lit2 == 0) { fprintf(f, " /* REM R%d,R%d */\n", r1, r2); fprintf(f, " if(gr%d != 0)\n", r2); fprintf(f, " gr%d = gr%d %% gr%d;\n", r1, r1, r2); } else if(op1 == 0x9 && op2 == 0x3 && lit2 == 0) { fprintf(f, " /* REMU R%d,R%d */\n", r1, r2); fprintf(f, " if(gr%d != 0)\n", r2); fprintf(f, " gr%d = (unsigned) gr%d %% (unsigned) gr%d;\n", r1, r1, r2); } else if(op1 == 0x9 && op2 == 0x8) { fprintf(f, " /* SRL3 R%d,R%d,#%d */\n", r1, r2, lit2); fprintf(f, " gr%d = (unsigned) gr%d >> %d;\n", r1, r2, (lit2 & 0x1f)); } else if(op1 == 0x9 && op2 == 0xa) { fprintf(f, " /* SRA3 R%d,R%d,#%d */\n", r1, r2, lit2); fprintf(f, " gr%d = gr%d >> %d;\n", r1, r2, (lit2 & 0x1f)); } else if(op1 == 0x9 && op2 == 0xc) { fprintf(f, " /* SLL3 R%d,R%d,#%d */\n", r1, r2, lit2); fprintf(f, " gr%d = gr%d << %d;\n", r1, r2, (lit2 & 0x1f)); } else if(op1 == 0x9 && op2 == 0xf && r2 == 0) { fprintf(f, " /* LDI R%d,#%d */\n", r1, lit2); fprintf(f, " gr%d = %d;\n", r1, lit2); } else if(op1 == 0xa && op2 == 0x0) { fprintf(f, " /* STB R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " (*(callbacks->store1))(0x%08x, gr%d + %d, gr%d & 0xff);\n", (unsigned)pc, r2, lit2, r1); } else if(op1 == 0xa && op2 == 0x2) { fprintf(f, " /* STH R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " (*(callbacks->store2))(0x%08x, gr%d + %d, gr%d & 0xffff);\n", (unsigned)pc, r2, lit2, r1); } else if(op1 == 0xa && op2 == 0x4) { fprintf(f, " /* ST R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " (*(callbacks->store))(0x%08x, gr%d + %d, gr%d);\n", (unsigned)pc, r2, lit2, r1); } else if(op1 == 0xa && op2 == 0x8) { fprintf(f, " /* LDB R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " gr%d = (*(callbacks->load1))(0x%08x, gr%d + %d);\n", r1, (unsigned)pc, r2, lit2); } else if(op1 == 0xa && op2 == 0x9) { fprintf(f, " /* LDUB R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " gr%d = (unsigned char)(*(callbacks->load1))(0x%08x, gr%d + %d);\n", r1, (unsigned)pc, r2, lit2); } else if(op1 == 0xa && op2 == 0xa) { fprintf(f, " /* LDH R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " gr%d = (*(callbacks->load2))(0x%08x, gr%d + %d);\n", r1, (unsigned)pc, r2, lit2); } else if(op1 == 0xa && op2 == 0xb) { fprintf(f, " /* LDUH R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " gr%d = (unsigned short)(*(callbacks->load2))(0x%08x, gr%d + %d);\n", r1, (unsigned)pc, r2, lit2); } else if(op1 == 0xa && op2 == 0xc) { fprintf(f, " /* LD R%d,@(%d,R%d) */\n", r1, lit2, r2); fprintf(f, " gr%d = (*(callbacks->load))(0x%08x, gr%d + %d);\n", r1, (unsigned)pc, r2, lit2); } else if(op1 == 0xb && op2 == 0x0) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BEQ R%d,R%d,%d */\n", r1, r2, lit2); fprintf(f, " if (gr%d == gr%d)\n", r1, r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xb && op2 == 0x1) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BNE R%d,R%d,%d */\n", r1, r2, lit2); fprintf(f, " if (gr%d != gr%d)\n", r1, r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xb && op2 == 0x8 && r1 == 0) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BEQZ R%d,%d */\n", r2, lit2); fprintf(f, " if (gr%d == 0)\n", r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xb && op2 == 0x9 && r1 == 0) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BNEZ R%d,%d */\n", r2, lit2); fprintf(f, " if (gr%d != 0)\n", r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xb && op2 == 0xa && r1 == 0x0) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BLTZ R%d,%d */\n", r2, lit2); fprintf(f, " if (gr%d < 0)\n", r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xb && op2 == 0xb && r1 == 0x0) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BGEZ R%d,%d */\n", r2, lit2); fprintf(f, " if (gr%d >= 0)\n", r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xb && op2 == 0xc && r1 == 0x0) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BLEZ R%d,%d */\n", r2, lit2); fprintf(f, " if (gr%d <= 0)\n", r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xb && op2 == 0xd && r1 == 0x0) { unsigned newpc = (pc & 0xfffffffc) + (((int) lit2) << 2); fprintf(f, " /* BGTZ R%d,%d */\n", r2, lit2); fprintf(f, " if (gr%d > 0)\n", r2); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xd && op2 == 0xc && r2 == 0) { fprintf(f, " /* SETH R%d,#%d */\n", r1, lit2); fprintf(f, " gr%d = 0x%08x;\n", r1, (lit2 << 16)); } else if(op1 == 0xe) { fprintf(f, " /* LD24 R%d,#%d */\n", r1, lit3); fprintf(f, " gr%d = 0x%08x;\n", r1, lit3); } else if(op1 == 0xf && r1 == 0xc) { unsigned newpc = (pc & 0xfffffffc) + (((lit3 << 8) >> 8) << 2); fprintf(f, " /* BC %d */\n", lit3); fprintf(f, " if (cond)\n"); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xf && r1 == 0xd) { unsigned newpc = (pc & 0xfffffffc) + (((lit3 << 8) >> 8) << 2); fprintf(f, " /* BNC %d */\n", lit3); fprintf(f, " if (! cond)\n"); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0xf && r1 == 0xe) { unsigned newpc = (pc & 0xfffffffc) + (((lit3 << 8) >> 8) << 2); unsigned retpc = (pc & 0xfffffffc) + 4; fprintf(f, " /* BL %d */\n", lit3); fprintf(f, " gr14 = 0x%08x;\n", retpc); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); } else if(op1 == 0xf && r1 == 0xf) { unsigned newpc = (pc & 0xfffffffc) + (((lit3 << 8) >> 8) << 2); fprintf(f, " /* BRA %d */\n", lit3); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); } else { /* illegal instruction */ /* XXX */ fprintf(f, " printf(\"ILLEGAL INSN 0x%08x @ PC 0x%08x\\n\");\n", insn, (unsigned)pc); fprintf(f, " abort();\n"); } } void m32r_emit_short_insn(sim_gx_block* gx, PCADDR pc, unsigned insn, int optimized) { int op1 = (insn & 0xf000) >> 12; int r1 = (insn & 0x0f00) >> 8; int op2 = (insn & 0x00f0) >> 4; int op2part = (insn & 0x00e0) >> 5; int r2 = (insn & 0x000f); signed char c = (insn & 0x00ff); signed char c5 = (insn & 0x001f); sim_gx_compiled_block* block = optimized ? gx->optimized_block : gx->learning_block; FILE* f = block->source_file; ASSERT(f != NULL); if(0) ; /* place holder */ else if(op1 == 0x0 && op2 == 0x0) { fprintf(f, " /* SUBV R%d,R%d */\n", r1, r2); fprintf(f, " temp = gr%d - gr%d;\n", r1, r2); fprintf(f, " cond = (unsigned) gr%d < (unsigned) gr%d;\n", r1, r2); fprintf(f, " gr%d = temp;\n", r1); } else if(op1 == 0x0 && op2 == 0x1) { fprintf(f, " /* SUBX R%d,R%d */\n", r1, r2); fprintf(f, " temp = gr%d - gr%d - (cond ? 1:0);\n", r1, r2); fprintf(f, " cond = (unsigned) gr%d < (unsigned) gr%d;\n", r1, r2); fprintf(f, " gr%d = temp;\n", r1); } else if(op1 == 0x0 && op2 == 0x2) { fprintf(f, " /* SUB R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d - gr%d;\n", r1, r1, r2); } else if(op1 == 0x0 && op2 == 0x3) { fprintf(f, " /* NEG R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = 0 - gr%d;\n", r1, r2); } else if(op1 == 0x0 && op2 == 0x4) { fprintf(f, " /* CMP R%d,R%d */\n", r1, r2); fprintf(f, " cond = (gr%d < gr%d);\n", r1, r2); } else if(op1 == 0x0 && op2 == 0x5) { fprintf(f, " /* CMPU R%d,R%d */\n", r1, r2); fprintf(f, " cond = ((unsigned) gr%d < (unsigned) gr%d);\n", r1, r2); } else if(op1 == 0x0 && op2 == 0x8) { fprintf(f, " /* ADDV R%d,R%d */\n", r1, r2); fprintf(f, " temp = gr%d + gr%d;\n", r1, r2); fprintf(f, " cond = ((gr%d & gr%d) | (gr%d & ~temp) | (gr%d & ~temp)) & (1<<31);\n", r1, r2, r1, r2); fprintf(f, " cond = (gr%d ^ gr%d ^ temp ^ cond) & (1<<31);\n", r1, r2); fprintf(f, " gr%d = temp;\n", r1); } else if(op1 == 0x0 && op2 == 0x9) { fprintf(f, " /* ADDX R%d,R%d */\n", r1, r2); fprintf(f, " temp = gr%d + gr%d + (cond ? 1:0);\n", r1, r2); fprintf(f, " cond = ((gr%d & gr%d) | (gr%d & ~temp) | (gr%d & ~temp)) & (1<<31);\n", r1, r2, r1, r2); fprintf(f, " gr%d = temp;\n", r1); } else if(op1 == 0x0 && op2 == 0xa) { fprintf(f, " /* ADD R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d + gr%d;\n", r1, r1, r2); } else if(op1 == 0x0 && op2 == 0xb) { fprintf(f, " /* NOT R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = ~ gr%d;\n", r1, r2); } else if(op1 == 0x0 && op2 == 0xc) { fprintf(f, " /* AND R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d & gr%d;\n", r1, r1, r2); } else if(op1 == 0x0 && op2 == 0xd) { fprintf(f, " /* XOR R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d ^ gr%d;\n", r1, r1, r2); } else if(op1 == 0x0 && op2 == 0xe) { fprintf(f, " /* OR R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d | gr%d;\n", r1, r1, r2); } else if(op1 == 0x1 && op2 == 0x0) { fprintf(f, " /* SRL R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = (unsigned) gr%d >> (gr%d & 0x1f);\n", r1, r1, r2); } else if(op1 == 0x1 && op2 == 0x2) { fprintf(f, " /* SRA R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d >> (gr%d & 0x1f);\n", r1, r1, r2); } else if(op1 == 0x1 && op2 == 0x4) { fprintf(f, " /* SLL R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d << (gr%d & 0x1f);\n", r1, r1, r2); } else if(op1 == 0x1 && op2 == 0x6) { fprintf(f, " /* MUL R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d * gr%d;\n", r1, r1, r2); } else if(op1 == 0x1 && op2 == 0x8) { fprintf(f, " /* MV R%d,R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d;\n", r1, r2); } else if(op1 == 0x1 && op2 == 0x9) { fprintf(f, " /* MVFC R%d,CR%d */\n", r1, r2); if(r2 == 0) /* psw */ fprintf(f, " gr%d = (cr0 & 0x00c140) | (sm ? 0x80 : 0 ) | (cond ? 1 : 0);\n", r1); else if(r2 == 1) /* cbr */ fprintf(f, " gr%d = (cond ? 1 : 0);\n", r1); else if(r2 == 2) /* spi */ { fprintf(f, " if (sm) gr%d = cr2;\n", r1); fprintf(f, " else gr%d = gr15;\n", r1); } else if(r2 == 3) /* spu */ { fprintf(f, " if (!sm) gr%d = cr3;\n", r1); fprintf(f, " else gr%d = gr15;\n", r1); } else fprintf(f, " gr%d = cr%d;\n", r1, r2); } else if(op1 == 0x1 && op2 == 0xa) { fprintf(f, " /* MVTC R%d,CR%d */\n", r1, r2); if(r2 == 0) /* psw */ { fprintf(f, " cr0 = gr%d & 0x0000c1c1;\n", r1); fprintf(f, " cond = cr0 & 1;\n"); fprintf(f, " cr2 = sm ? cr2 : gr15;\n"); fprintf(f, " cr3 = sm ? gr15 : cr3;\n"); fprintf(f, " sm = cr0 & 80;\n"); fprintf(f, " gr15 = sm ? cr3 : cr2;\n"); } else if(r2 == 1) /* cbr */ ; /* no effect */ else if(r2 == 2) /* spi */ { fprintf(f, " if (sm) cr2 = gr%d;\n", r1); fprintf(f, " else gr15 = gr%d;\n", r1); } else if(r2 == 3) /* spu */ { fprintf(f, " if (!sm) cr3 = gr%d;\n", r1); fprintf(f, " else gr15 = gr%d;\n", r1); } else if(r2 == 6) /* bpc */ fprintf(f, " cr6 = gr%d & 0xfffffffe;\n", r1); else fprintf(f, " cr%d = gr%d;\n", r1, r2); } else if(op1 == 0x1 && op2 == 0xc && r1 == 0xe) { fprintf(f, " /* JL R%d */\n", r2); fprintf(f, " gr14 = (0x%08x & 0xfffffffc) + 4;\n", (unsigned)pc); fprintf(f, " npc = gr%d & 0xfffffffc;\n", r2); fprintf(f, " goto unknownjump;\n"); } else if(op1 == 0x1 && op2 == 0xc && r1 == 0xf) { fprintf(f, " /* JMP R%d */\n", r2); fprintf(f, " npc = gr%d & 0xfffffffc;\n", r2); fprintf(f, " goto unknownjump;\n"); } else if(op1 == 0x1 && op2 == 0xd && r1 == 0x0 && r2 == 0x6) { fprintf(f, " /* RTE */\n"); fprintf(f, " cr0 = (cr0 & 0xff00) | (cr0 >> 8);\n"); fprintf(f, " cond = cr0 & 0x01;\n"); fprintf(f, " sm = cr0 & 0x80;\n"); fprintf(f, " gr15 = sm ? cr3 : cr2;\n"); fprintf(f, " npc = cr6 & 0xfffffffc;\n"); fprintf(f, " goto unknownjump;\n"); } else if(op1 == 0x1 && op2 == 0xf) { fprintf(f, " /* TRAP #%d */\n", r2); if (r2 == TRAP_SYSCALL) /* general syscall ABI */ { fprintf(f, " {\n"); fprintf(f, " tgx_syscall_data d = { 0x%08x, gr0, gr1, gr2, gr3 };\n", (unsigned) pc); fprintf(f, " (*(callbacks->syscall))(&d);\n"); fprintf(f, " gr2 = d.errcode;\n"); fprintf(f, " gr1 = d.result;\n"); fprintf(f, " gr0 = d.result2;\n"); fprintf(f, " }\n"); } else if (r2 == 1) /* gdb breakpoint */ { fprintf(f, " rc = %d;\n", GX_F_HALT); fprintf(f, " goto save;\n"); } else { fprintf(f, " cr6 = 0x%08x;\n", (unsigned)(pc + 4)); fprintf(f, " cr0 = (cr0 & 0x000040) | (sm ? 0x80 : 0 ) | (cond ? 1 : 0);\n"); fprintf(f, " cr0 = (cr0 & 0x0000ff) << 8 | (cr0 & 0x0000ff);\n"); fprintf(f, " npc = 0x%08x;\n", 0x40 + (r2 * 4)); /* EIT_TRAP_BASE_ADDR */ fprintf(f, " goto unknownjump;\n"); } } else if(op1 == 0x2 && op2 == 0x0) { fprintf(f, " /* STB R%d,@R%d */\n", r1, r2); fprintf(f, " (*(callbacks->store1))(0x%08x, gr%d, gr%d & 0xff);\n", (unsigned)pc, r2, r1); } else if(op1 == 0x2 && op2 == 0x2) { fprintf(f, " /* STH R%d,@R%d */\n", r1, r2); fprintf(f, " (*(callbacks->store2))(0x%08x, gr%d, gr%d & 0x0000ffff);\n", (unsigned)pc, r2, r1); } else if(op1 == 0x2 && op2 == 0x4) { fprintf(f, " /* ST R%d,@R%d */\n", r1, r2); fprintf(f, " (*(callbacks->store))(0x%08x, gr%d, gr%d);\n", (unsigned)pc, r2, r1); } else if(op1 == 0x2 && op2 == 0x5) { fprintf(f, " /* UNLOCK R%d,@R%d */\n", r1, r2); fprintf(f, " if(lock)\n"); fprintf(f, " {\n"); fprintf(f, " lock = 0;\n"); fprintf(f, " (*(callbacks->store))(0x%08x, gr%d, gr%d);\n", (unsigned)pc, r2, r1); fprintf(f, " }\n"); } else if(op1 == 0x2 && op2 == 0x6) { fprintf(f, " /* ST R%d,@+R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d + 4;\n", r2, r2); fprintf(f, " (*(callbacks->store))(0x%08x, gr%d, gr%d);\n", (unsigned)pc, r2, r1); } else if(op1 == 0x2 && op2 == 0x7) { fprintf(f, " /* ST R%d,@-R%d */\n", r1, r2); fprintf(f, " gr%d = gr%d - 4;\n", r2, r2); fprintf(f, " (*(callbacks->store))(0x%08x, gr%d, gr%d);\n", (unsigned)pc, r2, r1); } else if(op1 == 0x2 && op2 == 0x8) { fprintf(f, " /* LDB R%d,@R%d */\n", r1, r2); fprintf(f, " gr%d = (*(callbacks->load1))(0x%08x, gr%d);\n", r1, (unsigned)pc, r2); } else if(op1 == 0x2 && op2 == 0x9) { fprintf(f, " /* LDUB R%d,@R%d */\n", r1, r2); fprintf(f, " gr%d = (unsigned char)(*(callbacks->load1))(0x%08x, gr%d);\n", r1, (unsigned)pc, r2); } else if(op1 == 0x2 && op2 == 0xa) { fprintf(f, " /* LDH R%d,@R%d */\n", r1, r2); fprintf(f, " gr%d = (*(callbacks->load2))(0x%08x, gr%d);\n", r1, (unsigned)pc, r2); } else if(op1 == 0x2 && op2 == 0xb) { fprintf(f, " /* LDUH R%d,@R%d */\n", r1, r2); fprintf(f, " gr%d = (unsigned short)(*(callbacks->load2))(0x%08x, gr%d);\n", r1, (unsigned)pc, r2); } else if(op1 == 0x2 && op2 == 0xc) { fprintf(f, " /* LD R%d,@R%d */\n", r1, r2); fprintf(f, " gr%d = (*(callbacks->load))(0x%08x, gr%d);\n", r1, (unsigned)pc, r2); } else if(op1 == 0x2 && op2 == 0xd) { fprintf(f, " /* LOCK R%d,@R%d */\n", r1, r2); fprintf(f, " lock = 1;\n"); fprintf(f, " gr%d = (*(callbacks->load))(0x%08x, gr%d);\n", r1, (unsigned)pc, r2); } else if(op1 == 0x2 && op2 == 0xe) { fprintf(f, " /* LD R%d,@R%d+ */\n", r1, r2); fprintf(f, " gr%d = (*(callbacks->load))(0x%08x, gr%d);\n", r1, (unsigned)pc, r2); fprintf(f, " gr%d = gr%d + 4;\n", r2, r2); } else if(op1 == 0x4) { fprintf(f, " /* ADDI R%d,#%d */\n", r1, c); fprintf(f, " gr%d = gr%d + %d;\n", r1, r1, c); } else if(op1 == 0x5 && op2part == 0x0) { fprintf(f, " /* SRLI R%d,#%d */\n", r1, c5); fprintf(f, " gr%d = ((unsigned) gr%d) >> %d;\n", r1, r1, c5); } else if(op1 == 0x5 && op2part == 0x1) { fprintf(f, " /* SRAI R%d,#%d */\n", r1, c5); fprintf(f, " gr%d = gr%d >> %d;\n", r1, r1, c5); } else if(op1 == 0x5 && op2part == 0x2) { fprintf(f, " /* SRLI R%d,#%d */\n", r1, c5); fprintf(f, " gr%d = gr%d << %d;\n", r1, r1, c5); } else if(op1 == 0x6) { fprintf(f, " /* LDI R%d,#%d */\n", r1, c); fprintf(f, " gr%d = 0x%08x;\n", r1, c); } else if(op1 == 0x7 && r1 == 0xc) { unsigned newpc = (pc & 0xfffffffc) + (((int) c) << 2); fprintf(f, " /* BC %d */\n", c); fprintf(f, " if (cond)\n"); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0x7 && r1 == 0xd) { unsigned newpc = (pc & 0xfffffffc) + (((int) c) << 2); fprintf(f, " /* BNC %d */\n", c); fprintf(f, " if (! cond)\n"); fprintf(f, " {\n"); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); fprintf(f, " }\n"); } else if(op1 == 0x7 && r1 == 0xe) { unsigned newpc = (pc & 0xfffffffc) + (((int) c) << 2); unsigned retpc = (pc & 0xfffffffc) + 4; fprintf(f, " /* BL %d */\n", c); fprintf(f, " gr14 = 0x%08x;\n", retpc); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); } else if(op1 == 0x7 && r1 == 0xf) { unsigned newpc = (pc & 0xfffffffc) + (((int) c) << 2); fprintf(f, " /* BRA %d */\n", c); fprintf(f, " npc = 0x%08x;\n", newpc); fprintf(f, " goto %s;\n", (GX_PC_INCLUDES(gx,newpc)) ? "shortjump" : "longjump"); } else if(op1 == 0x7 && op2 == 0x0 && r1 == 0x0 && r1 == 0x0) { fprintf(f, " /* NOP */\n"); } else { /* illegal instruction */ /* XXX */ fprintf(f, " printf(\"ILLEGAL INSN 0x%04x @ PC 0x%08x\\n\");\n", insn, (unsigned) pc); fprintf(f, " abort();\n"); } }