void Ppc405Iss::op_b() { uint32_t base = m_ins.i.aa ? 0 : r_pc; if ( m_ins.i.lk ) r_lr = r_pc + 4; m_next_pc = base + sign_ext(m_ins.i.li<<2, 26); }
void EMips::decode(ULONG inst) { switch(opFormat) { case EMIPS_FORMAT_NONE: break; case EMIPS_FORMAT_CONST: imm=(op&0x03ffffff)<<2; ea=imm+(pc&0xf0000000); break; case EMIPS_FORMAT_REG_REG_CONST: rt=(op>>16)&0x1f; rs=(op>>21)&0x1f; imm=sign_ext(op&0xffff,16); break; case EMIPS_FORMAT_REG_REG_REG: sa=(op>>6)&0x1f; rd=(op>>11)&0x1f; rt=(op>>16)&0x1f; rs=(op>>21)&0x1f; break; case EMIPS_FORMAT_VARIOUS: if(!disFlag) { disFlag=true; disVarious(); disFlag=false; } else debugger("Caught in disVarious loop in decode!\n"); break; default: DEBUG_OUT<<"decode: opFormat is "<<opFormat<<"!\n"; DEBUG_OUT<<"decode: top was "<<top<<" bop was "<<bop<<"\n"; debugger("Bad opFormat in decode()!\n"); break; } }
/* Basic integer 3-address imm16 format: * mnemonic #imm16,%rs2,%rd */ static void int_i2d(std::ostream &stream, char *mnemonic, uint32_t pc, uint32_t insn) { /* Sign extend the 16-bit immediate. Print as hex for the bitwise operations. */ int upper_6bits = (insn >> 26) & 0x3f; if (upper_6bits >= 0x30 && upper_6bits <= 0x3f) util::stream_format(stream, "%s\t0x%04x,%%r%d,%%r%d", mnemonic, (uint32_t)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn)); else util::stream_format(stream, "%s\t%d,%%r%d,%%r%d", mnemonic, sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn)); }
/* Basic integer 3-address imm16 format: * mnemonic #imm16,%rs2,%rd */ static void int_i2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) { /* Sign extend the 16-bit immediate. Print as hex for the bitwise operations. */ int upper_6bits = (insn >> 26) & 0x3f; if (upper_6bits >= 0x30 && upper_6bits <= 0x3f) sprintf(buf, "%s\t0x%04x,%%r%d,%%r%d", mnemonic, (UINT32)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn)); else sprintf(buf, "%s\t%d,%%r%d,%%r%d", mnemonic, sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn)); }
// CLASS METHOD: Interpreter::exec_load_store_instr() // PURPOSE: Load/store instructions move data between memory and the // general registers. They are all encoded as "I-Type" // instructions, and the only addressing mode implemented is base // register plus signed, immediate offset. This directly enables // the use of three distinct addressing modes: register plus // offset; register direct; and immediate. // // ARGUMENTS: None. // RETURNS: None. void Interpreter::exec_load_store_instr(void) { Word vaddr, paddr; switch (op(curr_instr)) { // LB -- Load Byte // // Sign-extend 16-bit `offset` and add to contents of register `base` to // form address. Sign-extend contents of addressed byte and load into // `rt`. case LB: vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr); paddr = translate_address(align(vaddr)); do_load(LOADREG, rt(curr_instr), sign_ext_byte(mem->read(vaddr, paddr), bytepos(vaddr))); break; // LBU -- Load Byte Unsigned // // Sign-extend 16-bit `offse` and add to contents of register `base` to // form address. Zero-extend contents of addressed byte and load into // `rt`. case LBU: vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr); paddr = translate_address(align(vaddr)); do_load(LOADREG, rt(curr_instr), zero_ext_byte(mem->read(vaddr, paddr), bytepos(vaddr))); break; // LH -- Load Halfword // // Sign-extend 16-bit `offset` and add to contents of register `base` to // form address. Sign-extend contents of addressed byte and load into // `rt`. case LH: vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr); paddr = translate_address(align(vaddr)); do_load(LOADREG, rt(curr_instr), sign_ext_hword(mem->read(vaddr, paddr), hwordpos(vaddr))); break; // LHU -- Load Halfword Unsigned // // Sign-extend 16-bit `offset` and add to contents of register `base` to // form address. Zero-extend contents of addressed byte and load into // `rt`. case LHU: vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr); paddr = translate_address(align(vaddr)); do_load(LOADREG, rt(curr_instr), zero_ext_hword(mem->read(vaddr, paddr), hwordpos(vaddr))); break; // LW -- Load Word // // Sign-extend 16-bit `offset` and add to contents of register `base` to // form address. Load contents of addressed word into register `rt`. case LW: vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr); paddr = translate_address(align(vaddr)); do_load(LOADREG, rt(curr_instr), mem->read(vaddr, paddr)); break; // LWL -- Load Word Left // // Sign-extend 16-bit `offset` and add to contents of register `base` to // form address. Shift addressed word left so that addressed byte is // leftmost byte of a word. Merge bytes from memory with contents of // register `rt` and load result into register `rt`. case LWL: vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr); paddr = translate_address(align(vaddr)); do_load(LOADREG, rt(curr_instr), merge(gpr[rt(curr_instr)], mem->read(vaddr, paddr), bytepos(vaddr), true)); break; // LWR -- Load Word Right // // Sign-extend 16-bit `offset` and add to contents of register `base` to // form address. Shfit addressed word right so that addressed byte is // rightmost byte of a word. Merge bytes from memory with contents of // register `rt` and load result into register `rt`. case LWR: vaddr = gpr[base(curr_instr)] + sign_ext(curr_instr); paddr = translate_address(align(vaddr)); do_load(LOADREG, rt(curr_instr), merge(gpr[rt(curr_instr)], mem->read(vaddr, paddr), bytepos(vaddr), false)); break; // SB -- Store Byte // // Sign-extend 16-bit `offset` and add to contents of register `base` to // form address. Store least significant byte of register `rt` at // addressed location. } }
srcdest decode_bit (int destcode) { srcdest sd; int addr = 0; static const char *dc_names[] = { "r0", "r1", "r2", "r3", "a0", "a1", "[a0]", "[a1]", "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]", "disp16[a0]", "disp16[a1]", "disp16[sb]", "abs16" }; if (trace) { const char *the_bits = bits (destcode, 4); printf ("decode: %s : %s\n", the_bits, dc_names[destcode]); } switch (destcode) { case 0: sd.u.reg = r0; break; case 1: sd.u.reg = r1; break; case 2: sd.u.reg = r2; break; case 3: sd.u.reg = r3; break; case 4: sd.u.reg = a0; break; case 5: sd.u.reg = a1; break; case 6: addr = get_reg (a0); break; case 7: addr = get_reg (a1); break; case 8: addr = get_reg (a0) + disp8 (); break; case 9: addr = get_reg (a1) + disp8 (); break; case 10: addr = get_reg (sb) * 8 + disp8 (); break; case 11: addr = get_reg (fb) * 8 + sign_ext (disp8 (), 8); break; case 12: addr = get_reg (a0) + disp16 (); break; case 13: addr = get_reg (a1) + disp16 (); break; case 14: addr = get_reg (sb) + disp16 (); break; case 15: addr = disp16 (); break; } if (destcode < 6) { int d = disp8 (); sd.mem = 0; sd.mask = 1 << (d & 0x0f); } else { addr &= addr_mask; sd.mem = 1; sd.mask = 1 << (addr & 7); sd.u.addr = addr >> 3; } return sd; }
static srcdest decode_sd23 (int bbb, int bb, int bytes, int ind, int add) { srcdest sd; int code = (bbb << 2) | bb; if (code >= sizeof (modes23) / sizeof (modes23[0])) abort (); if (trace) { char *b1 = ""; char *b2 = ""; char ad[30]; if (ind) { b1 = "["; b2 = "]"; } if (add) sprintf (ad, "%+d", add); else ad[0] = 0; if (!the_bits) the_bits = bits (code, 4); printf ("decode: %s (%d) : %s%s%s%s\n", the_bits, code, b1, modes23[code].name, ad, b2); the_bits = 0; } sd.bytes = bytes; sd.mem = modes23[code].is_memory; if (sd.mem) { if (modes23[code].w_regno == mem) sd.u.addr = 0; else sd.u.addr = get_reg (modes23[code].w_regno); switch (modes23[code].disp_bytes) { case 1: sd.u.addr += disp8 (); break; case 2: sd.u.addr += disp16 (); break; case -1: sd.u.addr += sign_ext (disp8 (), 8); break; case -2: sd.u.addr += sign_ext (disp16 (), 16); break; case 3: sd.u.addr += disp24 (); break; default: break; } if (add) sd.u.addr += add; if (ind) sd.u.addr = mem_get_si (sd.u.addr & membus_mask); sd.u.addr &= membus_mask; } else { sd.u.reg = (bytes > 1) ? modes23[code].w_regno : modes23[code].b_regno; if (bytes == 3 || bytes == 4) { switch (sd.u.reg) { case r0: sd.u.reg = r2r0; break; case r1: sd.u.reg = r3r1; break; case r2: abort (); case r3: abort (); default:; } } } return sd; }
srcdest decode_jumpdest (int destcode, int w) { srcdest sd; sd.bytes = w ? 2 : 3; sd.mem = (destcode >= 6) ? 1 : 0; static const char *dc_wnames[16] = { "r0", "r1", "r2", "r3", "a0", "a1", "[a0]", "[a1]", "disp8[a0]", "disp8[a1]", "disp8[sb]", "disp8[fb]", "disp20[a0]", "disp20[a1]", "disp16[sb]", "abs16" }; static const char *dc_anames[4] = { "r0l", "r0h", "r1l", "r1h" }; if (trace) { const char *n = dc_wnames[destcode]; if (w == 0 && destcode <= 3) n = dc_anames[destcode]; if (!the_bits) the_bits = bits (destcode, 4); printf ("decode: %s : %s\n", the_bits, n); the_bits = 0; } switch (destcode) { case 0x0: sd.u.reg = w ? r0 : r2r0; break; case 0x1: sd.u.reg = w ? r1 : r2r0; break; case 0x2: sd.u.reg = w ? r2 : r3r1; break; case 0x3: sd.u.reg = w ? r3 : r3r1; break; case 0x4: sd.u.reg = w ? a0 : a1a0; break; case 0x5: sd.u.reg = w ? a1 : a1a0; break; case 0x6: sd.u.addr = get_reg (a0); break; case 0x7: sd.u.addr = get_reg (a1); break; case 0x8: sd.u.addr = get_reg (a0) + disp8 (); break; case 0x9: sd.u.addr = get_reg (a1) + disp8 (); break; case 0xa: sd.u.addr = get_reg (sb) + disp8 (); break; case 0xb: sd.u.addr = get_reg (fb) + sign_ext (disp8 (), 8); break; case 0xc: sd.u.addr = get_reg (a0) + disp20 (); break; case 0xd: sd.u.addr = get_reg (a1) + disp20 (); break; case 0xe: sd.u.addr = get_reg (sb) + disp16 (); break; case 0xf: sd.u.addr = disp16 (); break; default: abort (); } if (sd.mem) sd.u.addr &= addr_mask; return sd; }
void EArm::decode() { willExecute=false; cond=(opcode>>28)&0xf; op1.init(); op2.init(); op3.init(); unsigned int rn,rd,rs,rm,imm; switch(mode) { case EARM_NONE: break; case EARM_SPECIAL: decode_special(); break; case EARM_ILLEGAL: debugger("illegal mode in decode!"); break; case EARM_REG_IMM: rn=(opcode>>16)&0xf; rd=(opcode>>12)&0xf; rs=(opcode>>8)&0xf; opcode2=(opcode>>4)&0xf; imm=opcode&0xf; op1.mode=EARM_REG; op1.reg=rd; op2.mode=EARM_IMM; op2.val=imm; break; case EARM_REG_IMM2: rn=(opcode>>16)&0xf; rd=(opcode>>12)&0xf; rs=(opcode>>8)&0xf; opcode2=(opcode>>4)&0xf; imm=opcode&0xf; op1.mode=EARM_REG; op1.reg=rn; op2.mode=EARM_IMM; op2.val=imm; break; case EARM_REG_REG: rn=(opcode>>16)&0xf; rd=(opcode>>12)&0xf; rs=(opcode>>8)&0xf; opcode2=(opcode>>4)&0xf; rm=opcode&0xf; op1.mode=EARM_REG; op1.reg=rd; op2.mode=EARM_REG; op2.reg=rm; break; case EARM_REG_REG2: rn=(opcode>>16)&0xf; rd=(opcode>>12)&0xf; rs=(opcode>>8)&0xf; opcode2=(opcode>>4)&0xf; rm=opcode&0xf; op1.mode=EARM_REG; op1.reg=rn; op2.mode=EARM_REG; op2.reg=rm; break; case EARM_REG_REG_REG: rn=(opcode>>16)&0xf; rd=(opcode>>12)&0xf; rs=(opcode>>8)&0xf; opcode2=(opcode>>4)&0xf; rm=opcode&0xf; op1.mode=EARM_REG; op1.reg=rd; op2.mode=EARM_REG; op2.reg=rn; op3.mode=EARM_REG; op3.reg=rm; break; case EARM_REG_REG_IMM: rn=(opcode>>16)&0xf; rd=(opcode>>12)&0xf; rs=(opcode>>8)&0xf; opcode2=(opcode>>4)&0xf; imm=opcode&0xf; op1.mode=EARM_REG; op1.reg=rd; op2.mode=EARM_REG; op2.reg=rn; op3.mode=EARM_IMM; op3.val=imm; break; case EARM_DISP: imm=sign_ext(opcode&0xffffff,24); op1.mode=EARM_DISP; op1.val=imm*4; break; case EARM_REG_ADDR: rn=(opcode>>16)&0xf; rd=(opcode>>12)&0xf; imm=opcode&0xfff; op1.mode=EARM_REG; op1.reg=rd; op2.mode=EARM_INDREG; op2.reg=rn; op2.val=-imm; break; case EARM_MULTREG: rn=(opcode>>16)&0xf; imm=opcode&0xffff; op1.mode=EARM_REG; op1.reg=rn; op2.mode=EARM_MULTREG; op2.val=imm; break; default: DEBUG_OUT<<"Mode was "<<mode<<"\n"; debugger("unknown mode in decode!"); break; } if(cond==EARM_CC_NEVER) { decode_special(); } else { if(cond==EARM_CC_ALWAYS) willExecute=true; else { // TODO: Check cond code, set willExecute to true if necessary } } }
void Ppc405Iss::op_bc() { int32_t base = m_ins.b.aa ? 0 : r_pc; branch_cond( base + sign_ext(m_ins.i.li<<2, 16) ); }
void Ppc405Iss::op_addic_() { uint32_t tmp = do_addi( r_gp[m_ins.d.ra], sign_ext(m_ins.d.imm, 16), 0, true ); crSetSigned( 0, tmp, 0 ); }
void Ppc405Iss::op_addic() { do_addi( r_gp[m_ins.d.ra], sign_ext(m_ins.d.imm, 16), 0, true ); }
void Ppc405Iss::op_addi() { uint32_t base = m_ins.d.ra ? r_gp[m_ins.d.ra] : 0; do_addi( base, sign_ext(m_ins.d.imm, 16), 0, false ); }