/* * Write an ASCII disassembly of one instruction at "pc" * in "RAM" into "line" (max length "max_line"), return * number of bytes consumed. */ int arch_pdp11_disasm_instr(cpu_t *cpu, addr_t pc, char *line, unsigned int max_line) { uint16_t opcode = cpu->RAM[pc]; char line2[8]; int addmode = get_addmode(opcode); if (addmode == ADDMODE_BRA) { snprintf(line2, sizeof(line2), "$%02" PRIX64, pc+2 + (int8_t)cpu->RAM[pc+1]); } else { switch (get_length(addmode)) { case 1: snprintf(line2, sizeof(line2), addmode_template[addmode], 0); break; case 2: snprintf(line2, sizeof(line2), addmode_template[addmode], cpu->RAM[pc+1]); break; case 3: snprintf(line2, sizeof(line2), addmode_template[addmode], cpu->RAM[pc+1] | cpu->RAM[pc+2]<<8); break; default: printf("Table error at %s:%d\n", __FILE__, __LINE__); exit(1); } } snprintf(line, max_line, "%s %s", mnemo[get_instr(opcode)], line2); return get_length(get_addmode(cpu->RAM[pc])); }
static Value * arch_6502_get_operand_lvalue(cpu_t *cpu, addr_t pc, BasicBlock* bb) { int am = get_addmode(cpu->RAM[pc]); Value *index_register_before; Value *index_register_after; bool is_indirect; bool is_8bit_base; switch (am) { case ADDMODE_ACC: return ptr_A; case ADDMODE_BRA: case ADDMODE_IMPL: return NULL; case ADDMODE_IMM: { Value *ptr_temp = new AllocaInst(getIntegerType(8), "temp", bb); new StoreInst(CONST8(OPERAND_8), ptr_temp, bb); return ptr_temp; } } is_indirect = ((am == ADDMODE_IND) || (am == ADDMODE_INDX) || (am == ADDMODE_INDY)); is_8bit_base = !((am == ADDMODE_ABS) || (am == ADDMODE_ABSX) || (am == ADDMODE_ABSY)); index_register_before = NULL; if ((am == ADDMODE_ABSX) || (am == ADDMODE_INDX) || (am == ADDMODE_ZPX)) index_register_before = ptr_X; if ((am == ADDMODE_ABSY) || (am == ADDMODE_ZPY)) index_register_before = ptr_Y; index_register_after = (am == ADDMODE_INDY)? ptr_Y : NULL; #if 0 LOG("pc = %x\n", pc); LOG("index_register_before = %x\n", index_register_before); LOG("index_register_after = %x\n", index_register_after); LOG("is_indirect = %x\n", is_indirect); LOG("is_8bit_base = %x\n", is_8bit_base); #endif /* create base constant */ uint16_t base = is_8bit_base? (OPERAND_8):(OPERAND_16); Value *ea = CONST32(base); if (index_register_before) ea = ADD(ZEXT32(LOAD(index_register_before)), ea); /* wrap around in zero page */ if (is_8bit_base) ea = AND(ea, CONST32(0x00FF)); else if (base >= 0xFF00) /* wrap around in memory */ ea = AND(ea, CONST32(0xFFFF)); if (is_indirect) ea = ZEXT32(LOAD_RAM16(ea)); if (index_register_after) ea = ADD(ZEXT32(LOAD(index_register_after)), ea); return GEP(ea); }
int arch_6502_tag_instr(cpu_t *cpu, addr_t pc, tag_t *tag, addr_t *new_pc, addr_t *next_pc) { uint8_t opcode = cpu->RAM[pc]; switch (get_instr(opcode)) { case INSTR_BRK: *tag = TAG_TRAP; break; case INSTR_RTS: *tag = TAG_RET; break; case INSTR_JMP: if (get_addmode(opcode) == ADDMODE_ABS) *new_pc = cpu->RAM[pc+1] | cpu->RAM[pc+2]<<8; else *new_pc = NEW_PC_NONE; /* jmp indirect */ *tag = TAG_BRANCH; break; case INSTR_JSR: *new_pc = cpu->RAM[pc+1] | cpu->RAM[pc+2]<<8; *tag = TAG_CALL; break; case INSTR_BCC: case INSTR_BCS: case INSTR_BEQ: case INSTR_BMI: case INSTR_BNE: case INSTR_BPL: case INSTR_BVC: case INSTR_BVS: *new_pc = pc+2 + (int8_t)cpu->RAM[pc+1]; *tag = TAG_COND_BRANCH; break; default: //XXX only known instrunctions should be TAG_CONTINUE, //XXX all others should be TAG_TRAP *tag = TAG_CONTINUE; break; } int length = get_length(get_addmode(opcode)); *next_pc = pc + length; return length; }
int arch_pdp11_translate_instr(cpu_t *cpu, addr_t pc, BasicBlock *bb) { uint16_t opcode = cpu->RAM[pc]; //LOG("%s:%d PC=$%04X\n", __func__, __LINE__, pc); switch (get_instr(opcode)) { /* flags */ case INSTR_CLC: LET1(cpu->ptr_C, FALSE); break; case INSTR_CLD: LET1(ptr_D, FALSE); break; case INSTR_CLI: LET1(ptr_I, FALSE); break; case INSTR_CLV: LET1(cpu->ptr_V, FALSE); break; case INSTR_SEC: LET1(cpu->ptr_C, TRUE); break; case INSTR_SED: LET1(ptr_D, TRUE); break; case INSTR_SEI: LET1(ptr_I, TRUE); break; /* register transfer */ case INSTR_TAX: SET_NZ(LET(X,R(A))); break; case INSTR_TAY: SET_NZ(LET(Y,R(A))); break; case INSTR_TXA: SET_NZ(LET(A,R(X))); break; case INSTR_TYA: SET_NZ(LET(A,R(Y))); break; case INSTR_TSX: SET_NZ(LET(X,R(S))); break; case INSTR_TXS: SET_NZ(LET(S,R(X))); break; /* load */ case INSTR_LDA: SET_NZ(LET(A,OPERAND)); break; case INSTR_LDX: SET_NZ(LET(X,OPERAND)); break; case INSTR_LDY: SET_NZ(LET(Y,OPERAND)); break; /* store */ case INSTR_STA: STORE(R(A),LOPERAND); break; case INSTR_STX: STORE(R(X),LOPERAND); break; case INSTR_STY: STORE(R(Y),LOPERAND); break; /* stack */ case INSTR_PHA: PUSH(R(A)); break; case INSTR_PHP: PUSH(arch_flags_encode(cpu, bb)); break; case INSTR_PLA: SET_NZ(LET(A,PULL)); break; case INSTR_PLP: arch_flags_decode(cpu, PULL, bb); break; /* shift */ case INSTR_ASL: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, false)); break; case INSTR_LSR: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, false)); break; case INSTR_ROL: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, true, true)); break; case INSTR_ROR: SET_NZ(SHIFTROTATE(LOPERAND, LOPERAND, false, true)); break; /* bit logic */ case INSTR_AND: SET_NZ(LET(A,AND(R(A),OPERAND))); break; case INSTR_ORA: SET_NZ(LET(A,OR(R(A),OPERAND))); break; case INSTR_EOR: SET_NZ(LET(A,XOR(R(A),OPERAND))); break; case INSTR_BIT: SET_NZ(OPERAND); break; /* arithmetic */ case INSTR_ADC: SET_NZ(ADC(ptr_A, ptr_A, OPERAND, true, false)); break; case INSTR_SBC: SET_NZ(ADC(ptr_A, ptr_A, COM(OPERAND), true, false)); break; case INSTR_CMP: SET_NZ(ADC(NULL, ptr_A, COM(OPERAND), false, true)); break; case INSTR_CPX: SET_NZ(ADC(NULL, ptr_X, COM(OPERAND), false, true)); break; case INSTR_CPY: SET_NZ(ADC(NULL, ptr_Y, COM(OPERAND), false, true)); break; /* increment/decrement */ case INSTR_INX: SET_NZ(LET(X,INC(R(X)))); break; case INSTR_INY: SET_NZ(LET(Y,INC(R(Y)))); break; case INSTR_DEX: SET_NZ(LET(X,DEC(R(X)))); break; case INSTR_DEY: SET_NZ(LET(Y,DEC(R(Y)))); break; case INSTR_INC: SET_NZ(STORE(INC(OPERAND),LOPERAND)); break; case INSTR_DEC: SET_NZ(STORE(DEC(OPERAND),LOPERAND)); break; /* control flow */ case INSTR_JMP: if (get_addmode(opcode) == ADDMODE_IND) { Value *v = LOAD_RAM16(CONST32(OPERAND_16)); new StoreInst(v, cpu->ptr_PC, bb); } break; case INSTR_JSR: PUSH16(pc+2); break; case INSTR_RTS: STORE(ADD(PULL16, CONST16(1)), cpu->ptr_PC); break; /* branch */ case INSTR_BEQ: case INSTR_BNE: case INSTR_BCS: case INSTR_BCC: case INSTR_BMI: case INSTR_BPL: case INSTR_BVS: case INSTR_BVC: break; /* other */ case INSTR_NOP: break; case INSTR_BRK: arch_6502_trap(cpu, pc, bb); break; case INSTR_RTI: arch_6502_trap(cpu, pc, bb); break; case INSTR_XXX: arch_6502_trap(cpu, pc, bb); break; } return get_length(get_addmode(opcode)); }