Пример #1
0
def get_imm_SB(imm10, lineno):
    try:
        imm10 = int(imm10)
    except:
        msg = "Invalid immediate specified."
        return False, imm10, msg
    '''
    The SB type encodes instructions BEQ, BNE, BLT, BLTU, BGE, BGEU.
    The 12 bit immediate is encodes a signed offset in multiples of two.
    Hence the last bit will be 0 and we ignore this in the encoding
    effectively allowing encoding up to 13 bits.
    '''
    # 13 bit encoding
    IMM_MAX = 0b0111111111110
    IMM_MIN = -0b1000000000000

    if (imm10 > IMM_MAX) or (imm10 < IMM_MIN):
        cp.cprint_warn("Warning:" + str(lineno) + ":" +
                       "Immediate is too big, will overflow.")
    # Convert to 2's complement binary
    imm2 = format(imm10 if imm10 >= 0 else (1 << 13) + imm10, '013b')
    if imm2[-1] != '0':
        cp.cprint_warn("Warning:" + str(lineno) + ":" +
                       "Immediate not 2 bytes aligned. Last bit will" +
                       "be dropped.")
    imm2 = imm2[0:12]
    # Convert immediate back to base 10 from base 2
    # p[0] = int(imm2, 2)
    assert (len(imm2) == 12)
    imm_12_10_5 = imm2[-12] + imm2[-10:-4]
    imm_4_1_11 = imm2[-4:] + imm2[-11]
    assert (len(imm_12_10_5) + len(imm_4_1_11) == 12)
    return True, (imm_12_10_5, imm_4_1_11), None
Пример #2
0
def get_imm_U(imm10, lineno):
    try:
        imm10 = int(imm10)
    except:
        msg = "Invalid immediate specified."
        return False, imm10, msg
    '''
    The U type immediate occurs in LUI and AUIPC instructions.
    From the point of a compiler/assembler, there is nothing in
    particular that has to be checked about this immediate except
    that it fits into the 20 bit width.
    '''
    IMM_MAX = 0b01111111111111111111
    IMM_MIN = -0b10000000000000000000

    if (imm10 > IMM_MAX) or (imm10 < IMM_MIN):
        cp.cprint_warn("Warning:" + str(p.lineno(1)) + ":" +
                       "Immediate is too big, will overflow.")
    # Conver to 2's complement binary
    imm2 = format(imm10 if imm10 >= 0 else (1 << 20) + imm10, '020b')
    imm2 = imm2[-20:]
    # Convert immediate back to base 10 from base 2
    # p[0] = int(imm2, 2)
    assert (len(imm2) == 20)
    return True, imm2, None
Пример #3
0
    def op_arithi(self, tokens):
        '''
        imm[11:0]   rs1 funct3   rd  opcode

        The immediate for SLLI and SRLI needs to have the upper
        7 bets set to 0 and for SRAI, it needs to be set to
        0100000
        '''
        opcode = tokens['opcode']
        bin_opcode = None
        funct3 = None
        rs1 = None
        bin_rs1 = None
        bin_rd = None
        rd = None
        imm = None

        try:
            funct3 = self.CONST.FUNCT3_ARITHI[opcode]
            bin_opcode = self.CONST.BOP_ARITHI
            rs1 = tokens['rs1']
            bin_rs1 = self.get_bin_register(rs1)
            rd = tokens['rd']
            bin_rd = self.get_bin_register(rd)
            imm = tokens['imm']
        except:
            cp.cprint_fail("Internal Error: ARITHI: could not parse" +
                           "tokens in " + str(tokens['lineno']))
            exit()

        bin_str = imm + bin_rs1 + funct3 + bin_rd + bin_opcode
        assert (len(bin_str) == 32)

        if opcode in (self.CONST.INSTR_SLLI, self.CONST.INSTR_SRLI):
            if imm[0:7] != '0000000':
                cp.cprint_warn("Warning:" + str(tokens['lineno']) +
                               ": Upper 7 bits of immediate should be 0")

        if opcode in (self.CONST.INSTR_SRAI):
            if imm[0:7] != '0100000':
                cp.cprint_warn("Warning:" + str(tokens['lineno']) +
                               ": Upper 7 bits of immediate should be " +
                               "01000000")

        tok_dict = {
            'opcode': bin_opcode,
            'funct3': funct3,
            'rs1': bin_rs1,
            'rd': bin_rd,
            'imm': imm
        }
        return bin_str, tok_dict
Пример #4
0
def get_imm_UJ(imm10, lineno):
    try:
        imm10 = int(imm10)
    except:
        msg = "Invalid immediate specified."
        return False, imm10, msg
    '''
    The UJ Type immediate encodes a 2 byte aligned address.
    Hence its last bit has to be zero. We do not encode this
    last bit in the instruction and the CPU assumes the last
    bit to be zero.
    The immediate is reshuffled and looks like the following.

    imm[20] imm[10:1] imm[11] imm[19:12]
    Note that imm[0] is not encoded.

    From the parsers point of view, we accept an (21 bit) immediate
    check if its a multiple of 2 (report and error)
    and then shuffle it as required
    '''
    # Effectively we are addressing 21 bits
    IMM_MAX = 0b011111111111111111110
    IMM_MIN = -0b100000000000000000000

    if (imm10 > IMM_MAX) or (imm10 < IMM_MIN):
        cp.cprint_warn("Warning:" + str(lineno) + ":" +
                       "Immediate is too big, will overflow.")
    # Conver to 2's complement binary
    imm2 = format(imm10 if imm10 >= 0 else (1 << 21) + imm10, '021b')
    if imm2[-1:] != '0':
        cp.cprint_warn("Warning:" + str(lineno) + ":" +
                       "Immediate not 2 bytes aligned. Last bit will" +
                       "be dropped.")
    imm2 = imm2[0:-1]
    assert (len(imm2) == 20)
    # Shuffling the immediate
    # imm[20] imm[10:1] imm[11] imm[19:12]
    # Indexing in reverse order
    # imm[20] in is imm2[0] = imm2[-20] of imm string
    shf_imm = imm2[0] + imm2[10:20] + imm2[9] + imm2[1:9]
    assert (len(shf_imm) == 20)
    return True, shf_imm, None
Пример #5
0
def get_imm_I(imm10, lineno):
    try:
        imm10 = int(imm10)
    except:
        msg = "Invalid immediate specified."
        return False, imm10, msg
    '''
    The I type immediates occur in all immediate arithmetic
    and logic operations, JALR, LW, LB, LH, LBU and LHU

    In the arithmetic/logic instructions, SLTUI is the only
    unsigned operation. Even in SLTUI, the immediate is
    sign extended first before an unsigned comparison is made
    hence for our purposes, the immediate is a signed 12 bit
    binary number.

    For JALR, the 12 bit immediate is sign extended and the CPU
    sets the lowest bit to 0 on its own before jumping. If a misaligned
    address is provided, it is the CPU's job to generate exceptions.
    Hence we check again for a 12 bit signed immediate.

    For LW, LB, LH, LBU and LHU, the address is a signed 12 bit
    number. Since the ISA allows misaligned loads, we need not check
    for alignment. Again, the CPU generates a misaligned instruction
    exception if required.

    Since I am generating a assembler for a 32 bit architecture, a warning
    is generated for misaligned loads in the binary generation phase.
    '''
    IMM_MAX = 0b011111111111
    IMM_MIN = -0b100000000000

    if (imm10 > IMM_MAX) or (imm10 < IMM_MIN):
        cp.cprint_warn("Warning:" + str(lineno) + ":" +
                       "Immediate is too big, will overflow.")
    # Conver to 2's complement binary
    imm2 = format(imm10 if imm10 >= 0 else (1 << 12) + imm10, '012b')
    imm2 = imm2[-12:]
    # Convert immediate back to base 10 from base 2
    # p[0] = int(imm2, 2)
    assert (len(imm2) == 12)
    return True, imm2, p_statement_none
Пример #6
0
def get_imm_S(imm10, lineno):
    try:
        imm10 = int(imm10)
    except:
        msg = "Invalid immediate specified."
        return False, imm10, msg
    '''
    The S type encodes instructions SW, SB and SH.
    Similar to loads, SW, SB and SH the address offset is a signed 12 bit
    number. Since the ISA allows misaligned stores, we need not check
    for alignment. Again, the CPU generates a misaligned instruction
    exception if required.

    Since I am generating a assembler for a 32 bit architecture, a warning
    is generated for misaligned stores in the binary generation phase.

    Also, in S type, the immediate is split into two parts - one part
    holding bits [11:5] in the immediate ordering(MSB-LSB from left to right)
    and the other part holding bits [4:0].
    We split the immediate into two portions hence.
    '''
    IMM_MAX = 0b011111111111
    IMM_MIN = -0b100000000000

    if (imm10 > IMM_MAX) or (imm10 < IMM_MIN):
        cp.cprint_warn("Warning:" + str(lineno) + ":" +
                       " Immediate is too big, will overflow.")
    # Convert to 2's complement binary
    imm2 = format(imm10 if imm10 >= 0 else (1 << 12) + imm10, '012b')
    if imm2[-1] != 0:
        cp.cprint_warn("Warning:" + str(lineno) + ":" +
                       "Immediate not 2 bytes aligned. Last bit will" +
                       "be dropped.")
    imm2 = imm2[0:12]
    # Convert immediate back to base 10 from base 2
    # p[0] = int(imm2, 2)
    assert (len(imm2) == 12)
    imm_11_5 = imm2[:7]
    imm_4_0 = imm2[7:]
    assert (len(imm_11_5) + len(imm_4_0) == 12)
    return True, (imm_11_5, imm_4_0), p_statement_none