def execute_bl(s, inst): if condition_passed(s, inst.cond): s.rf[LR] = trim_32(s.fetch_pc() + 4) offset = signed(sext_30(inst.imm_24) << 2) s.rf[PC] = trim_32(signed(s.rf[PC]) + offset) return s.rf[PC] = s.fetch_pc() + 4
def execute_fmax_s(s, inst): a, b = trim_32(s.fp[inst.rs1]), trim_32(s.fp[inst.rs2]) # TODO: s.fp[ inst.rd ] = sfp.isNaNF32UI(b) || ... s.fp[inst.rd] = a if sfp.f32_le_quiet(b, a) else b s.fcsr = sfp.get_flags() sfp.set_flags(0) s.pc += 4
def execute_bl( s, inst ): if condition_passed( s, inst.cond ): s.rf[LR] = trim_32( s.fetch_pc() + 4 ) offset = signed( sext_30( inst.imm_24 ) << 2 ) s.rf[PC] = trim_32( signed( s.rf[PC] ) + offset ) return s.rf[PC] = s.fetch_pc() + 4
def execute_fmax_s( s, inst ): a, b = trim_32( s.fp[inst.rs1] ), trim_32( s.fp[inst.rs2] ) # TODO: s.fp[ inst.rd ] = sfp.isNaNF32UI(b) || ... s.fp[ inst.rd ] = a if sfp.f32_le_quiet(b,a) else b s.fcsr = sfp.get_flags() sfp.set_flags( 0 ) s.pc += 4
def execute_sc_d(s, inst): addr = s.rf[inst.rs1] if addr == s.load_reservation: s.mem.write(addr, 4, trim_32(s.rf[inst.rs2])) s.mem.write(addr + 4, 4, trim_32(s.rf[inst.rs2] >> 32)) s.rf[inst.rd] = 0 else: s.rf[inst.rd] = 1 s.pc += 4
def execute_amoand_d(s, inst): addr = s.rf[inst.rs1] value = (( s.mem.read( addr+4, 4 ) << 32 ) \ | s.mem.read( addr, 4 )) new = value & s.rf[inst.rs2] s.mem.write(addr, 4, trim_32(new)) s.mem.write(addr + 4, 4, trim_32(new >> 32)) s.rf[inst.rd] = value s.pc += 4
def execute_amomax_d( s, inst ): addr = s.rf[inst.rs1] value = (( s.mem.read( addr+4, 4 ) << 32 ) \ | s.mem.read( addr, 4 )) new = max( signed(value, 64), signed(s.rf[inst.rs2], 64) ) s.mem.write( addr, 4, trim_32( new ) ) s.mem.write( addr+4, 4, trim_32( new >> 32 ) ) s.rf[inst.rd] = value s.pc += 4
def execute_sc_d( s, inst ): addr = s.rf[inst.rs1] if addr == s.load_reservation: s.mem.write( addr, 4, trim_32( s.rf[inst.rs2] ) ) s.mem.write( addr+4, 4, trim_32( s.rf[inst.rs2] >> 32 ) ) s.rf[inst.rd] = 0 else: s.rf[inst.rd] = 1 s.pc += 4
def execute_amoand_d( s, inst ): addr = s.rf[inst.rs1] value = (( s.mem.read( addr+4, 4 ) << 32 ) \ | s.mem.read( addr, 4 )) new = value & s.rf[inst.rs2] s.mem.write( addr, 4, trim_32( new ) ) s.mem.write( addr+4, 4, trim_32( new >> 32 ) ) s.rf[inst.rd] = value s.pc += 4
def execute_amomax_d(s, inst): addr = s.rf[inst.rs1] value = (( s.mem.read( addr+4, 4 ) << 32 ) \ | s.mem.read( addr, 4 )) new = max(signed(value, 64), signed(s.rf[inst.rs2], 64)) s.mem.write(addr, 4, trim_32(new)) s.mem.write(addr + 4, 4, trim_32(new >> 32)) s.rf[inst.rd] = value s.pc += 4
def test_execute_arith_shift_right_imm(rn, imm, is16bit): rd = 2 state = new_state(rf0=trim_32(rn)) instr = (opcode_factory.asr16_immediate(rd=rd, rn=0, imm=imm) if is16bit else opcode_factory.asr32_immediate(rd=rd, rn=0, imm=imm)) name, executefn = decode(instr) executefn(state, Instruction(instr, None)) expected_state = StateChecker(AZ=(False if rn < 0 else True), # 1 >> 5 == 0 AV=0, AC=0, pc=((2 if is16bit else 4) + RESET_ADDR), rf2=(trim_32(-1) if rn < 0 else 0)) expected_state.check(state)
def test_execute_logical_shift_right(rn, rm, is16bit): rd = 2 state = new_state(rf0=trim_32(rn), rf1=trim_32(rm)) instr = (opcode_factory.lsr16(rd=rd, rn=0, rm=1) if is16bit else opcode_factory.lsr32(rd=rd, rn=0, rm=1)) name, executefn = decode(instr) executefn(state, Instruction(instr, None)) expected_state = StateChecker(AZ=(False if rn < 0 else True), # 1 >> 5 == 0 AV=0, AC=0, pc=((2 if is16bit else 4) + RESET_ADDR), rf2=(0b1111 if rn < 0 else 0)) expected_state.check(state)
def execute_trap16(s, inst): """The TRAP instruction causes the processor to halt and wait for external inputs. The immediate field within the instruction opcode is not processed by the hardware but can be used by software such as a debugger or operating system to find out the reason for the TRAP instruction. """ import pydgin.syscalls syscall_funcs = { 2: pydgin.syscalls.syscall_open, 3: pydgin.syscalls.syscall_close, 4: pydgin.syscalls.syscall_read, 5: pydgin.syscalls.syscall_write, 6: pydgin.syscalls.syscall_lseek, 7: pydgin.syscalls.syscall_unlink, 10: pydgin.syscalls.syscall_fstat, 15: pydgin.syscalls.syscall_stat, # 19: get_time_of_day, # TODO r0 = time pointer, r1 = timezone pointer 21: pydgin.syscalls.syscall_link, } # Undocumented traps: 0, 1, 2, 6. These are listed as "Reserved" in # the reference manual, but have been reported to appear in real programs. if inst.t5 == 0 or inst.t5 == 1 or inst.t5 == 2 or inst.t5 == 6: if inst.t5 == 0: # Write. syscall_handler = syscall_funcs[5] elif inst.t5 == 1: # Read. syscall_handler = syscall_funcs[4] elif inst.t5 == 2: # Open. syscall_handler = syscall_funcs[2] else: # Close. syscall_handler = syscall_funcs[3] retval, errno = syscall_handler(s, s.rf[0], s.rf[1], s.rf[2]) s.rf[0] = trim_32(retval) s.rf[3] = errno elif inst.t5 == 3: # Exit. syscall_handler = pydgin.syscalls.syscall_exit retval, errno = syscall_handler(s, s.rf[0], s.rf[1], s.rf[2]) elif inst.t5 == 4: if s.debug.enabled('syscalls'): print 'TRAP: Assertion SUCCEEDED.' elif inst.t5 == 5: if s.debug.enabled('syscalls'): print 'TRAP: Assertion FAILED.' elif inst.t5 == 7: # Initiate system call. syscall_handler = syscall_funcs[s.rf[3]] retval, errno = syscall_handler(s, s.rf[0], s.rf[1], s.rf[2]) # Undocumented: s.rf[0] = trim_32(retval) s.rf[3] = errno else: print ('WARNING: syscall not implemented: %d. Should be unreachable' % inst.t5) s.pc += 2
def execute_bic( s, inst ): if condition_passed( s, inst.cond ): a, (b, cout) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = a & trim_32(~b) s.rf[ inst.rd ] = trim_32( result ) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = cout if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_bic(s, inst): if condition_passed(s, inst.cond): a, (b, cout) = s.rf[inst.rn], shifter_operand(s, inst) result = a & trim_32(~b) s.rf[inst.rd] = trim_32(result) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = cout if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_bcond(s, inst): """ B<COND>: IF (Passed)<COND>)) then PC = PC + (SignExtend(SIMM) << 1) BL: LR = next PC; PC = PC + (SignExtend(SIMM) << 1) """ if is16bit: inst.bits &= 0xFFFF cond = inst.cond imm = inst.bcond_imm if cond == 0 and imm == 0: raise RuntimeError( ( "Epiphany simulator caught infinite loop at runtime. " + "Instruction at pc=%s is attempting to " + "branch unconditionally to itself." ) % hex(s.pc) ) if cond == 0b1111: # Branch and link (BL). s.rf[epiphany.isa.reg_map["LR"]] = s.pc + (2 if is16bit else 4) if condition_passed(s, cond): offset = (signed(sext_8(imm)) << 1) if is16bit else (signed(sext_24(imm)) << 1) s.pc = trim_32(s.pc + offset) else: s.pc += 2 if is16bit else 4 s.debug_flags()
def execute_adc(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = a + b + s.C s.rf[inst.rd] = trim_32(result) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = carry_from(result) s.V = overflow_from_add(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_sbc(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = intmask(a - b - (not s.C)) s.rf[inst.rd] = trim_32(result) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = not_borrow_from(result) s.V = overflow_from_sub(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_div( s, inst ): x = signed( s.rf[ inst.rs ] ) y = signed( s.rf[ inst.rt ] ) sign = -1 if (x < 0)^(y < 0) else 1 s.rf[ inst.rd ] = trim_32( abs(x) / abs(y) * sign ) s.pc += 4
def execute_adc( s, inst ): if condition_passed( s, inst.cond ): a, (b, _) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = a + b + s.C s.rf[ inst.rd ] = trim_32( result ) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = carry_from( result ) s.V = overflow_from_add( a, b, result ) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_mvn( s, inst ): if condition_passed( s, inst.cond ): a, cout = shifter_operand( s, inst ) result = trim_32( ~a ) s.rf[ inst.rd ] = result if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = cout s.V = s.V if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_sbc( s, inst ): if condition_passed( s, inst.cond ): a, (b, _) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = intmask( a - b - (not s.C) ) s.rf[ inst.rd ] = trim_32( result ) if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = not_borrow_from( result ) s.V = overflow_from_sub( a, b, result ) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_mvn(s, inst): if condition_passed(s, inst.cond): a, cout = shifter_operand(s, inst) result = trim_32(~a) s.rf[inst.rd] = result if inst.S: if inst.rd == 15: raise FatalError('Writing SPSR not implemented!') s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = cout s.V = s.V if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def farith(s, inst): """ RD = RN <OP> RM BN = RD[31] if (RD[30:0] == 0) { BZ=1 } else { BZ=0 } if (UnbiasedExponent(RD) > 127) { BUV=1 } else { BV=0 } if (UbiasedExponent(RD) < -126) { BUS=1 } else { BUS=BUS } if (RM or RN == NAN) { BIS=1 } else { BIS=BIS } BVS = BVS | BV; """ if is16bit: inst.bits &= 0xffff rd = bits2float(s.rf[inst.rd]) rn = bits2float(s.rf[inst.rn]) rm = bits2float(s.rf[inst.rm]) # Binary operations. if name == 'add': result = rn + rm elif name == 'sub': result = rn - rm elif name == 'mul': result = rn * rm elif name == 'madd': result = rd + (rn * rm) elif name == 'msub': result = rd - (rn * rm) # Unary operations. elif name == 'float': result = float(s.rf[inst.rn]) elif name == 'fix': if math.isnan(rn): # FXIME result = 0xffffffff else: result = int(rn) elif name == 'abs': result = abs(rn) # 'result' is always a Python float. # RD = RN <OP> RM s.rf[inst.rd] = trim_32(result if name == 'fix' else float2bits(result)) # BN = RD[31] s.BN = True if result < 0.0 else False # if (RD[30:0] == 0) { BZ=1 } else { BZ=0 } s.BZ = True if abs(result) < 0.0001 else False # if (UnbiasedExponent(RD) > 127) { BUV=1 } else { BV=0 } s.BUV = True if get_exponent(s.rf[inst.rd]) > 127 else False # if (UbiasedExponent(RD) < -126) { BUS=1 } else { BUS=BUS } if get_exponent(s.rf[inst.rd]) > 127: s.BUS = True # if (RM or RN == NAN) { BIS=1 } else { BIS=BIS } if ((is_unary and math.isnan(rn)) or (not is_unary) and (math.isnan(rn) or math.isnan(rm))): s.BIS = True # BVS = BVS | BV; s.BVS = s.BVS or s.BV s.debug_flags() s.pc += 2 if is16bit else 4
def addressing_mode_2( s, inst ): # Immediate vs. Register Offset if not inst.I: index = inst.imm_12 else: index, _ = shifter_operand_imm(s, inst) Rn = s.rf[inst.rn] offset_addr = Rn + index if inst.U else Rn - index # Offset Addressing/Pre-Indexed Addressing vs. Post-Indexed Addressing if inst.P: addr = offset_addr else: addr = Rn # Offset Addressing vs. Pre-/Post-Indexed Addressing if not (inst.P ^ inst.W): s.rf[inst.rn] = trim_32( offset_addr ) return trim_32( addr )
def addressing_mode_2(s, inst): # Immediate vs. Register Offset if not inst.I: index = inst.imm_12 else: index, _ = shifter_operand_imm(s, inst) Rn = s.rf[inst.rn] offset_addr = Rn + index if inst.U else Rn - index # Offset Addressing/Pre-Indexed Addressing vs. Post-Indexed Addressing if inst.P: addr = offset_addr else: addr = Rn # Offset Addressing vs. Pre-/Post-Indexed Addressing if not (inst.P ^ inst.W): s.rf[inst.rn] = trim_32(offset_addr) return trim_32(addr)
def execute_mov( s, inst ): if condition_passed( s, inst.cond ): if inst.rd == 15 and inst.S: # if not CurrentModeHasSPSR(): CPSR = SPSR # else: UNPREDICTABLE raise FatalError('UNPREDICTABLE in user and system mode!') result, cout = shifter_operand( s, inst ) s.rf[ inst.rd ] = trim_32( result ) if inst.S: s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = cout s.V = s.V if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_jr(s, inst): """ LR = PC + 2 (16 bit) 4 (32 bit) JALR only. PC = RN; """ if is16bit: inst.bits &= 0xffff if save_lr: s.rf[epiphany.isa.reg_map['LR']] = trim_32(s.pc + (2 if is16bit else 4)) s.pc = s.rf[inst.rn]
def execute_mov(s, inst): if condition_passed(s, inst.cond): if inst.rd == 15 and inst.S: # if not CurrentModeHasSPSR(): CPSR = SPSR # else: UNPREDICTABLE raise FatalError('UNPREDICTABLE in user and system mode!') result, cout = shifter_operand(s, inst) s.rf[inst.rd] = trim_32(result) if inst.S: s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = cout s.V = s.V if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_blx2(s, inst): if condition_passed(s, inst.cond): s.rf[LR] = trim_32(s.fetch_pc() + 4) s.T = s.rf[inst.rm] & 0x00000001 s.rf[PC] = s.rf[inst.rm] & 0xFFFFFFFE if s.T: raise FatalError("Entering THUMB mode! Unsupported!") # no pc + 4 on success else: s.rf[PC] = s.fetch_pc() + 4
def addressing_mode_4( s, inst ): IA = 0b01 IB = 0b11 DA = 0b00 DB = 0b10 mode = (inst.P << 1) | inst.U Rn = s.rf[ inst.rn ] nbytes = 4 * popcount( inst.register_list ) if mode == IA: start_addr, end_addr = Rn, Rn+nbytes-4 elif mode == IB: start_addr, end_addr = Rn+4, Rn+nbytes elif mode == DA: start_addr, end_addr = Rn-nbytes+4, Rn else: start_addr, end_addr = Rn-nbytes, Rn-4 if inst.W: s.rf[ inst.rn ] = trim_32( (Rn + nbytes) if inst.U else (Rn - nbytes) ) return trim_32( start_addr ), trim_32( end_addr )
def execute_blx2( s, inst ): if condition_passed( s, inst.cond ): s.rf[LR] = trim_32( s.fetch_pc() + 4 ) s.T = s.rf[ inst.rm ] & 0x00000001 s.rf[PC] = s.rf[ inst.rm ] & 0xFFFFFFFE if s.T: raise FatalError( "Entering THUMB mode! Unsupported!") # no pc + 4 on success else: s.rf[PC] = s.fetch_pc() + 4
def execute_smull( s, inst ): if condition_passed( s, inst.cond ): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') RdHi, RdLo = inst.rn, inst.rd Rm, Rs = signed(s.rf[ inst.rm ]), signed(s.rf[ inst.rs ]) result = Rm * Rs if RdHi == RdLo: raise FatalError('UNPREDICTABLE') s.rf[ RdHi ] = trim_32( result >> 32 ) s.rf[ RdLo ] = trim_32( result ) if inst.S: s.N = (result >> 63)&1 s.Z = result == 0 s.rf[PC] = s.fetch_pc() + 4
def addressing_mode_4(s, inst): IA = 0b01 IB = 0b11 DA = 0b00 DB = 0b10 mode = (inst.P << 1) | inst.U Rn = s.rf[inst.rn] nbytes = 4 * popcount(inst.register_list) if mode == IA: start_addr, end_addr = Rn, Rn + nbytes - 4 elif mode == IB: start_addr, end_addr = Rn + 4, Rn + nbytes elif mode == DA: start_addr, end_addr = Rn - nbytes + 4, Rn else: start_addr, end_addr = Rn - nbytes, Rn - 4 if inst.W: s.rf[inst.rn] = trim_32((Rn + nbytes) if inst.U else (Rn - nbytes)) return trim_32(start_addr), trim_32(end_addr)
def addressing_mode_3(s, inst): if inst.SH == 0b00: raise FatalError('Not a load/store instruction!') # Immediate vs. Register Offset if inst.B: index = (inst.imm_H << 4) | inst.imm_L else: index = s.rf[inst.rm] Rn = s.rf[inst.rn] offset_addr = Rn + index if inst.U else Rn - index # Offset Addressing/Pre-Indexed Addressing vs. Post-Indexed Addressing if inst.P: addr = offset_addr else: addr = Rn # Offset Addressing vs. Pre-/Post-Indexed Addressing if not (inst.P ^ inst.W): s.rf[inst.rn] = trim_32(offset_addr) return trim_32(addr)
def addressing_mode_3( s, inst ): if inst.SH == 0b00: raise FatalError('Not a load/store instruction!') # Immediate vs. Register Offset if inst.B: index = (inst.imm_H << 4) | inst.imm_L else: index = s.rf[inst.rm] Rn = s.rf[inst.rn] offset_addr = Rn + index if inst.U else Rn - index # Offset Addressing/Pre-Indexed Addressing vs. Post-Indexed Addressing if inst.P: addr = offset_addr else: addr = Rn # Offset Addressing vs. Pre-/Post-Indexed Addressing if not (inst.P ^ inst.W): s.rf[inst.rn] = trim_32( offset_addr ) return trim_32( addr )
def execute_umull(s, inst): if condition_passed(s, inst.cond): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') RdHi, RdLo = inst.rn, inst.rd Rm, Rs = s.rf[inst.rm], s.rf[inst.rs] result = Rm * Rs if RdHi == RdLo: raise FatalError('UNPREDICTABLE') s.rf[RdHi] = trim_32(result >> 32) s.rf[RdLo] = trim_32(result) if inst.S: s.N = (result >> 63) & 1 s.Z = (s.rf[RdHi] == s.rf[RdLo] == 0) s.rf[PC] = s.fetch_pc() + 4
def execute_smlal(s, inst): if condition_passed(s, inst.cond): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') RdHi, RdLo = inst.rn, inst.rd Rm, Rs = signed(s.rf[inst.rm]), signed(s.rf[inst.rs]) accumulate = (s.rf[RdHi] << 32) | s.rf[RdLo] result = (Rm * Rs) + signed(accumulate) if RdHi == RdLo: raise FatalError('UNPREDICTABLE') s.rf[RdHi] = trim_32(result >> 32) s.rf[RdLo] = trim_32(result) if inst.S: s.N = (result >> 63) & 1 s.Z = (s.rf[RdHi] == s.rf[RdLo] == 0) s.rf[PC] = s.fetch_pc() + 4
def execute_smlal( s, inst ): if condition_passed( s, inst.cond ): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') RdHi, RdLo = inst.rn, inst.rd Rm, Rs = signed(s.rf[ inst.rm ]), signed(s.rf[ inst.rs ]) accumulate = (s.rf[ RdHi ] << 32) | s.rf[ RdLo ] result = (Rm * Rs) + signed( accumulate ) if RdHi == RdLo: raise FatalError('UNPREDICTABLE') s.rf[ RdHi ] = trim_32( result >> 32 ) s.rf[ RdLo ] = trim_32( result ) if inst.S: s.N = (result >> 63)&1 s.Z = (s.rf[RdHi] == s.rf[RdLo] == 0) s.rf[PC] = s.fetch_pc() + 4
def test_single_inst_sub32(): from pydgin.utils import trim_32 instructions = [(opcode_factory.sub32_immediate(rd=1, rn=0, imm=0b01010101010), 32), (opcode_factory.bkpt16(), 16)] epiphany = MockEpiphany() epiphany.init_state(instructions, rf0=5) assert epiphany.state.running epiphany.run() expected_state = StateChecker(AZ=0, AN=1, AC=0, pc=(6 + RESET_ADDR), rf1=trim_32(5 - 0b01010101010)) expected_state.check(epiphany.state) assert not epiphany.state.running
def execute_tst(s, inst): if condition_passed(s, inst.cond): a, (b, cout) = s.rf[inst.rn], shifter_operand(s, inst) result = trim_32(a & b) if inst.S: s.N = (result >> 31) & 1 s.Z = result == 0 s.C = cout if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_cmp( s, inst ): if condition_passed( s, inst.cond ): a, (b, _) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = intmask( a - b ) s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = not_borrow_from( result ) s.V = overflow_from_sub( a, b, result ) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_cmn(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = a + b s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = carry_from(result) s.V = overflow_from_add(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_cmn( s, inst ): if condition_passed( s, inst.cond ): a, (b, _) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = a + b s.N = (result >> 31)&1 s.Z = trim_32( result ) == 0 s.C = carry_from( result ) s.V = overflow_from_add( a, b, result ) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_cmp(s, inst): if condition_passed(s, inst.cond): a, (b, _) = s.rf[inst.rn], shifter_operand(s, inst) result = intmask(a - b) s.N = (result >> 31) & 1 s.Z = trim_32(result) == 0 s.C = not_borrow_from(result) s.V = overflow_from_sub(a, b, result) if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_tst( s, inst ): if condition_passed( s, inst.cond ): a, (b, cout) = s.rf[ inst.rn ], shifter_operand( s, inst ) result = trim_32( a & b ) if inst.S: s.N = (result >> 31)&1 s.Z = result == 0 s.C = cout if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_bit(s, inst): """RD = RN <OP> RM AN = RD[31] AV = 0 AC = 0 If ( RD[31:0] == 0 ) { AZ=1 } else { AZ=0 } """ if is16bit: inst.bits &= 0xffff rm = inst.imm5 if imm else s.rf[inst.rm] if name == "and": result = s.rf[inst.rn] & rm elif name == "orr": result = s.rf[inst.rn] | rm elif name == "eor": result = s.rf[inst.rn] ^ rm elif name == "asr": result = signed(s.rf[inst.rn]) >> rm elif name == "lsr": result = s.rf[inst.rn] >> rm elif name == "lsl": result = s.rf[inst.rn] << rm elif name == "bitr": # The description of this instruction is confused in the ISA # reference. The decode table states that the instruction always # takes an intermediate, but the description of the instruction # states that it does not. result = 0 for i in range(32): if (s.rf[inst.rn] & (1 << i)): result |= (1 << (32 - 1 - i)) s.rf[inst.rd] = trim_32(result) s.AN = bool((result >> 31) & 1) s.AC = False s.AV = False s.AZ = True if trim_32(result) == 0 else False s.debug_flags() s.pc += 2 if is16bit else 4
def shifter_operand_reg(s, inst): shift_op = inst.shift Rm = s.rf[inst.rm] Rs = s.rf[inst.rs] & 0xFF out = cout = 0 if shift_op == LOGIC_SHIFT_LEFT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out, cout = Rm << Rs, (Rm >> 32 - Rs) & 1 elif Rs == 32: out, cout = 0, (Rm) & 1 elif Rs > 32: out, cout = 0, 0 elif shift_op == LOGIC_SHIFT_RIGHT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out, cout = Rm >> Rs, (Rm >> (Rs - 1)) & 1 elif Rs == 32: out, cout = 0, (Rm >> 31) & 1 elif Rs > 32: out, cout = 0, 0 elif shift_op == ARITH_SHIFT_RIGHT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out = arith_shift(Rm, Rs) cout = (Rm >> (Rs - 1)) & 1 elif Rs >= 32: out = 0 if ((Rm >> 31) == 0) else 0xFFFFFFFF cout = (Rm >> 31) & 1 elif shift_op == ROTATE_RIGHT: Rs4 = Rs & 0b1111 if Rs == 0: out, cout = Rm, s.C elif Rs4 == 0: out, cout = Rm, (Rm >> 31) & 1 elif Rs4 > 0: out, cout = rotate_right(Rm, Rs4), (Rm >> Rs4 - 1) & 1 else: raise FatalError("Impossible shift_op!") return trim_32(out), cout
def test_single_inst_sub32(): from pydgin.utils import trim_32 instructions = [(opcode_factory.sub32_immediate(rd=1, rn=0, imm=0b01010101010), 32), (opcode_factory.trap16(3), 16)] revelation = MockRevelation() revelation.init_state(instructions, rf0=5) assert revelation.states[0x808].running exit_code, ticks = revelation.run() expected_state = StateChecker(AZ=0, AN=1, AC=0, pc=(6 + RESET_ADDR), rf1=trim_32(5 - 0b01010101010)) expected_state.check(revelation.states[0x808]) assert EXIT_SUCCESS == exit_code assert len(instructions) == ticks assert not revelation.states[0x808].running
def execute_mul(s, inst): if condition_passed(s, inst.cond): Rm, Rs = s.rf[inst.rm], s.rf[inst.rs] result = trim_32(Rm * Rs) s.rf[inst.rn] = result if inst.S: if inst.rn == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') s.N = (result >> 31) & 1 s.Z = result == 0 if inst.rd == 15: return s.rf[PC] = s.fetch_pc() + 4
def execute_mla(s, inst): if condition_passed(s, inst.cond): if inst.rd == 15: raise FatalError('UNPREDICTABLE') if inst.rm == 15: raise FatalError('UNPREDICTABLE') if inst.rs == 15: raise FatalError('UNPREDICTABLE') if inst.rn == 15: raise FatalError('UNPREDICTABLE') Rm, Rs, Rd = s.rf[inst.rm], s.rf[inst.rs], s.rf[inst.rd] result = trim_32(Rm * Rs + Rd) s.rf[inst.rn] = result if inst.S: s.N = (result >> 31) & 1 s.Z = result == 0 s.rf[PC] = s.fetch_pc() + 4
def do_syscall(s): syscall_number = s.rf[v4] arg0 = intmask(s.rf[a1]) arg1 = intmask(s.rf[a2]) arg2 = intmask(s.rf[a3]) if syscall_number not in syscall_funcs: print "WARNING: syscall not implemented: %d" % syscall_number # TODO: return an error? else: syscall_handler = syscall_funcs[syscall_number] # call the syscall handler and get the return and error values retval, errno = syscall_handler(s, arg0, arg1, arg2) if s.debug.enabled("syscalls"): print " retval=%x errno=%x" % (retval, errno) s.rf[a1] = trim_32(retval)
def multhi64(a, b): # returns the high 64 bits of 64 bit multiplication # using this trick to get the high bits of 64-bit multiplication: # http://stackoverflow.com/questions/28868367/getting-the-high-part-of-64-bit-integer-multiplication a_hi, a_lo = trim_32(a >> 32), trim_32(a) b_hi, b_lo = trim_32(b >> 32), trim_32(b) a_x_b_hi = a_hi * b_hi a_x_b_mid = a_hi * b_lo b_x_a_mid = b_hi * a_lo a_x_b_lo = a_lo * b_lo carry_bit = (trim_32(a_x_b_mid) + trim_32(b_x_a_mid) + (a_x_b_lo >> 32)) >> 32 return a_x_b_hi + (a_x_b_mid >> 32) + (b_x_a_mid >> 32) + carry_bit
def shifter_operand_reg(s, inst): shift_op = inst.shift Rm = s.rf[inst.rm] Rs = s.rf[inst.rs] & 0xFF out = cout = 0 if shift_op == LOGIC_SHIFT_LEFT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out, cout = Rm << Rs, (Rm >> 32 - Rs) & 1 elif Rs == 32: out, cout = 0, (Rm) & 1 elif Rs > 32: out, cout = 0, 0 elif shift_op == LOGIC_SHIFT_RIGHT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out, cout = Rm >> Rs, (Rm >> (Rs - 1)) & 1 elif Rs == 32: out, cout = 0, (Rm >> 31) & 1 elif Rs > 32: out, cout = 0, 0 elif shift_op == ARITH_SHIFT_RIGHT: if Rs == 0: out, cout = Rm, s.C elif Rs < 32: out = arith_shift(Rm, Rs) cout = (Rm >> (Rs - 1)) & 1 elif Rs >= 32: out = 0 if ((Rm >> 31) == 0) else 0xFFFFFFFF cout = (Rm >> 31) & 1 elif shift_op == ROTATE_RIGHT: Rs4 = Rs & 0b1111 if Rs == 0: out, cout = Rm, s.C elif Rs4 == 0: out, cout = Rm, (Rm >> 31) & 1 elif Rs4 > 0: out, cout = rotate_right(Rm, Rs4), (Rm >> Rs4 - 1) & 1 else: raise FatalError('Impossible shift_op!') return trim_32(out), cout
def shifter_operand_imm(s, inst): shift_op = inst.shift Rm = s.rf[inst.rm] shift_imm = inst.shift_amt assert 0 <= shift_imm <= 31 if shift_op == LOGIC_SHIFT_LEFT: out = Rm if (shift_imm == 0) else Rm << shift_imm cout = s.C if (shift_imm == 0) else (Rm >> 32 - shift_imm) & 1 elif shift_op == LOGIC_SHIFT_RIGHT: # NOTE: shift_imm == 0 signifies a shift by 32 out = 0 if (shift_imm == 0) else Rm >> shift_imm cout = Rm >> 31 if (shift_imm == 0) else (Rm >> shift_imm - 1) & 1 elif shift_op == ARITH_SHIFT_RIGHT: # NOTE: shift_imm == 0 signifies a shift by 32 if shift_imm == 0: if (Rm >> 31) == 0: out, cout = 0, Rm >> 31 else: out, cout = 0xFFFFFFFF, Rm >> 31 else: out = arith_shift(Rm, shift_imm) cout = (Rm >> shift_imm - 1) & 1 elif shift_op == ROTATE_RIGHT: # NOTE: shift_imm == 0 signifies a rotate right with extend (RRX) if shift_imm == 0: out = (r_uint(s.C) << 31) | (Rm >> 1) cout = Rm & 1 else: out = rotate_right(Rm, shift_imm) cout = (Rm >> shift_imm - 1) & 1 else: raise FatalError('Impossible shift_op!') return trim_32(out), cout
def execute_trunc_w_s( s, inst ): # TODO: check for overflow x = bits2float( s.rf[ inst.fs ] ) s.rf[ inst.fd ] = trim_32(int(x)) # round down s.pc += 4
def execute_cvt_w_s( s, inst ): x = bits2float( s.rf[ inst.fs ] ) s.rf[ inst.fd ] = trim_32( int( x ) ) s.pc += 4
def execute_amo_add( s, inst ): temp = s.mem.read( s.rf[ inst.rs ], 4 ) s.mem.write( s.rf[inst.rs], 4, trim_32(temp + s.rf[inst.rt]) ) s.rf[ inst.rd ] = temp s.pc += 4
def execute_sb( s, inst ): addr = trim_32( s.rf[inst.rs] + sext_16(inst.imm) ) s.mem.write( addr, 1, s.rf[inst.rt] ) s.pc += 4