// shifts or rotates an lvalue left or right, regardless of width Value * arch_shiftrotate(cpu_t *cpu, Value *dst, Value *src, bool left, bool rotate, BasicBlock *bb) { Value *c; Value *v = LOAD(src); if (left) { c = ICMP_SLT(v, CONSTs(SIZE(v), 0)); /* old MSB to carry */ v = SHL(v, CONSTs(SIZE(v), 1)); if (rotate) v = OR(v,ZEXT(SIZE(v), LOAD(cpu->ptr_C))); } else { c = TRUNC1(v); /* old LSB to carry */ v = LSHR(v, CONSTs(SIZE(v), 1)); if (rotate) v = OR(v,SHL(ZEXT(SIZE(v), LOAD(cpu->ptr_C)), CONSTs(SIZE(v), SIZE(v)-1))); } LET1(cpu->ptr_C, c); return STORE(v, dst); }
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)); }