Exemple #1
0
    def build(self, asm, parsers, stmt, n, length, trace=False):
        if length != 2:
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type explicit length invalid: %s" % (n+1,length))

        value = parsers.evaluate_expr(asm,
                                      stmt,
                                      self.expr,
                                      debug=False,
                                      trace=trace)

        if isinstance(value, int):
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type value not an address: %s" % (n+1,value))

        try:
            base, disp = asm.bases.find(value, 12, asm, trace=trace)
        except KeyError:
            # Could not resolve base register and displacement
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s S-type constant could not resolve implied base "
                "register for location: %s" % (n+1,value)) from None

        value = (base << 12) + (0xFFF & disp)
        b = value.to_bytes(2, byteorder="big", signed=False)

        if __debug__:
            if trace:
                print("%s return bytes: %s '%s'" \
                    % (assembler.eloc(self,"build",module=this_module),len(b),b))

        return b
Exemple #2
0
    def parse_scope(self,stmt,parser,scope=None,required=False):
        prsr=self.__fetch_parser(parser)

        if stmt.opnd_fld:
            string=stmt.opnd_fld.text
        else:
            string=None

        if scope is not None:
            scp=scope
        else:
            scp=prsr._init_scope(scope=None)

        scp.statement(stmt)  # Tell the scope what statement is being parsed

        if string is None:
            if required:
                raise assembler.AssemblerError(source=stmt.source,line=stmt.lineno,\
                    msg="required operand field missing")
            else:
                return scp

        # There are operands to parse...
        try:
            # Returns a likely subclassed asmfsmbp.AsmFSMScope object
            return self.__parse(prsr,string,scope=scp)
        except assembler.AsmParserError as ape:
            lpos=stmt.opnd_fld.ndx2loc(ape.token.linepos)
            raise assembler.AssemblerError(source=stmt.source,line=stmt.lineno,\
                linepos=lpos.pndx+1,msg=ape.msg) from None
Exemple #3
0
    def parse_operands(self,stmt,parser,scope=None,required=False):
        # If the parse is for operands then the source and string positions
        # are different than if this is a statement field parse using an FSM-based
        # parser

        opnd=stmt.opnd_fld
        if opnd is not None:
            loc=opnd.start()
            source=loc.source
            string=opnd.text
            operpos=loc.pndx
        else:
            source=stmt.logline.source
            string=None

        # Only parse operands if they are actually present in the statement
        if string is None:
            if required:
                raise assembler.AssemblerError(source=source,line=stmt.lineno,\
                    msg="%s operation required operand field missing" % stmt.instu)
            else:
                return None

        try:
            # Returns a asmfsmbp.xxxScope object
            return self.__parse(parser,string,scope=scope)
        except assembler.AsmParserError as ape:
            raise assembler.AssemblerError(source=source,line=stmt.lineno,\
                msg=ape.msg) from None
Exemple #4
0
 def xmode_setting(self, stmt, mode, setting):
     try:
         mdict = self.xmode_dir[mode]
     except KeyError:
         raise assembler.AssemblerError(line=stmt.lineno,\
             msg="XMODE mode not recognized: %s" % mode) from None
     try:
         self.__xmode_setting(mode, setting, mdict)
     except KeyError:
         raise assembler.AssemblerError(line=stmt.lineno,\
             msg="XMODE %s setting invalid: %s" % (mode,setting)) from None
Exemple #5
0
    def __source(self, typ, sid, stmtno=None, srcno=0, fixed=False):
        if len(self._sources) >= self._depth:
            raise assembler.AssemblerError(line=stmtno,\
                msg="nested input source depth reached: %s" % self._depth)
        src_cls = LineBuffer.source_type[typ]
        srco = src_cls(typ, sid, srcno=srcno, fixed=fixed)
        try:
            srco.init(pathmgr=self._opath, variable=self._env)
        except SourceError as se:
            raise assembler.AssemblerError(line=stmtno, msg=se.msg) from None

        # Input source now ready to be used
        self.__appendSource(srco)
Exemple #6
0
 def evaluate_expr(self,asm,stmt,expr,debug=False,trace=False):
     try:
         return expr.evaluate(external=asm,debug=debug,trace=False)
     except pratt3.PParserError as pe:
         # Convert PParserError into an AssemblerError.  The PParserError object
         # may contain an object generated by the PParser object without a
         # source.  Before using the src for the AssemblerError we need to
         # make sure it is valid.  If all else fails, simply convert the
         # ptok to a printable string and use whatever results.
         raise assembler.AssemblerError(line=stmt.lineno,linepos=pe.pos,msg=pe.msg) \
             from None
     except assembler.LabelError as le:
         # Convert LabelError into an AssemblerError
         raise assembler.AssemblerError(line=stmt.lineno,linepos=le.ltok.linepos,\
             msg=le.msg) from None
Exemple #7
0
    def insert(self, length, inst, bldr, line, signed=False):
        value = self.value
        try:
            bldr.range_check(self.size, value, signed=signed)
        except RangeCheckError as re:
            raise assembler.AssemblerError(line=line,\
                msg="%s field %s" \
                    % (self.name,re)) from None

        # Prepare value for insertion into instruction if needed.
        if signed:
            uint = bldr.s2u_int(value, self.size)
        else:
            uint = value

        # This codes takes the field and
        # positions it for insertion into
        # the instruction being built
        #                                 # |0                         inst_bits|         |
        #  This diagram shows what        # |            |<-field->|            |
        #  this code is doing to          # <----------instruction-------------->
        #  accomplish this.               #              ^         ^  |   uint  |
        inst_bits = length * 8  #              |         |  |         |
        unshifted = inst_bits - self.size  #              |         |  +<--unshifted
        #              |    left |  |
        left_shift = unshifted - self.start  # field start->+<---shift---+
        to_insert = uint << left_shift  #              |  field  |
        #              | in pos. |

        # This adds the field to the instruction
        inst |= to_insert
        return inst  # This is the instruction with the new field added to it
Exemple #8
0
 def validate(self):
     logline=self.logline
     try:
         logline.validate()
     except asmcards.LineError as le:
         raise assembler.AssemblerError(source=le.source,line=self.lineno,\
             msg=le.msg) from None
Exemple #9
0
    def build(self, asm, parsers, stmt, n, length, trace=False):
        try:
            value = parsers.evaluate_expr(asm,
                                          stmt,
                                          self.expr,
                                          debug=False,
                                          trace=trace)
        except assembler.AddrArithError as ae:
            raise assembler.AssemblerError(line=stmt.lineno,\
                msg="operand %s address arithmetic error, %s" \
                    % (n+1,ae))

        assert isinstance(value,(int,assembler.Address)),\
            "%s internal calculation of operand %s address expression resulted in an"\
            "unsupported value: %s" \
            % (assembler.eloc(self,"build",module=this_module),n+1,value)

        if isinstance(value, assembler.Address):
            if length not in self.lengths:
                raise assembler.AssemblerError(line=stmt.lineno,\
                    msg="operand %s %s-type explicit length invalid for an address "\
                    "nominal value: %s" % (n+1,self.typ,length))
            if value.isAbsolute():
                value = value.address
            else:
                raise assembler.AssemblerError(line=stmt.lineno,\
                    msg="operand %s address constant did not evaluate to an "\
                        "absolute address: %s" % (n+1,value))

        # Convert computed address constant to bytes
        b = value.to_bytes((value.bit_length() // 8) + 1,
                           byteorder="big",
                           signed=False)

        # Perform left truncation/padding
        pad = b'\x00' * length
        bindata = pad + b
        b = bindata[len(bindata) - length:]

        if __debug__:
            if trace:
                print("%s return bytes: %s '%s'" % (assembler.eloc(
                    self, "build", module=this_module), len(b), b))

        return b
Exemple #10
0
    def __exhausted(self):
        # Current source is done
        try:
            self._cur_src.fini()
        except SourceError as se:
            # This is a fatal uncaught exception
            raise assembler.AssemblerError(msg=se.msg) from None

        # Unnest one input source
        self._sources.pop()
        if len(self._sources)==0:
            raise BufferEmpty from None  # All sources done, tell the assembler
        self._cur_src=self._sources[-1]
Exemple #11
0
 def newFile(self,filename,stmtno=None):
     #fname=os.path.abspath(filename)
     fname=filename
     # Detection of recursion requires work
     for src in self._sources:
         if src._typ!="F":
             continue
         if src.fname==fname:
             raise assembler.AssemblerError(line=stmtno,\
                 msg="nested file recursion encountered for file: %s" \
                     % (fname))
     # No recursion, safe to add as source
     self._fileno+=1
     self.__source("F",filename,stmtno=stmtno,srcno=self._fileno)
Exemple #12
0
 def __parse(self, asm, stmt, field, debug=False):
     ddebug = self.debug or debug
     if __debug__:
         if ddebug:
             print("%s [%s] field.amp: %s" \
                 % (assembler.eloc(self,"__parse",module=this_module),\
                     stmt.lineno,field.amp))
     if not field.amp:
         return field.text
     pm = asm.PM
     try:
         return pm.parse_model(stmt, field, debug=ddebug)
     except assembler.AsmParserError as ape:
         raise assembler.AssemblerError(source=stmt.source,line=stmt.lineno,\
             msg=ape.msg)
Exemple #13
0
    def operand_new(self,gs,trace=False):
        if trace:
            cls_str="asmparsers.py - %s.operand_new()" % self.__class__.__name__
            print(cls_str)
        gs.cur_operand=None
        stmt=gs.stmt
        if gs.operands==gs.next_oprndx:
            raise assembler.AssemblerError(line=gs.lineno,msg="too many operands")
        try:
            gs.cur_operand=stmt.get_operand(gs.next_oprndx)
        except IndexError:
            cls_str="asmparsers.py - %s.new_operand() -" % self.__class__.__name__
            raise ValueError("%s INTERNAL operand not supported: %s" \
                % (cls_str,gs.next_oprndx)) from None
        gs.next_oprndx+=1

        self.operand_init(gs,trace=trace)
Exemple #14
0
    def fields(self, fmt):
        mach = fmt.mach  # Dictionary of machine field definitions
        my_fields = []
        # Determine values for all fixed content fields
        vector = False
        for mfield, mf in mach.items():
            vector = vector or mf.typ == "V"  # Detect vector registers
            if not mf.fixed:
                continue
            try:
                fixed_value = self.fixed[mfield]
            except KeyError:
                # WARNING: this should not occur if msldb has done a proper validation.
                # Correct the bug in msldb.py if this is raised.
                raise ValueError("%s instruction definition does not define "
                    "fixed value for field: %s"\
                        % (eloc(self,"fields",module=this_module),mfield))
            fld = Field(mfield=mf, value=fixed_value)
            my_fields.append(fld)

        # Process values from statement operands
        rxb = 0
        for mfield in self.soper.mfields:
            try:
                mf = mach[mfield]
                # mf is the msldb.mfield object for which the operand provides its value
            except KeyError:
                # WARNING: this should not occur if msldb has done proper validation.
                # Correct the bug in msldb.py if this is raised.
                raise ValueError("%s instruction format %s does not define mach "
                    "field: %s" % (eloc(self,"fields",module=this_module),\
                        fmt.ID,mfield))

            mf_typ = mf.typ  # This is the machine field type
            # The Operand object now provides its value for this mfield type
            value = self.operand.field(mf_typ)
            if mf_typ == "V":
                if value < 0 or value > 31:
                    raise assembler.AssemblerError(line=line,\
                        msg="%s field outside of valid vector register range: %s" \
                            % (mf.name,value))
                vreg = value & 0xF
                if value > 15:
                    rxb |= mf.rxb
                fld = Field(mfield=mf, value=vreg)
            else:
                fld = Field(mfield=mf, value=value)
            my_fields.append(fld)

        # Generate RXB field if required
        if rxb:
            try:
                mf_rxb = mach["RXB"]
            except KeyError:
                # WARNING: this should not occur if msldb has done a proper validation.
                # Correct the bug in msldb.py if this is raised.
                raise ValueError(\
                    "%s instruction definition does not define field RXB" \
                        % assembler.eloc(self,"fields",module=this_module))
            fld = Field(mfield=mf_rxb, value=rxb)
            my_fields.append(fld)

        return my_fields
Exemple #15
0
 def validate_operand(self,line,n,trace=False):
     operand=self.operand
     ok=operand.validate_source(self.exprs,trace=trace)
     if not ok:
         raise assembler.AssemblerError(line=line,msg=operand.source_error())
     return
Exemple #16
0
 def Pass0(self,stmt,scope,debug=False):
     try:
         scope.Pass0(stmt,self,debug=debug)
     except assmebler.AsmParserError as ape:
         raise assembler.AssemblerError(source=stmt.source,line=stmt.lineno,\
              linepos=ape.token.linepos+1,msg=ape.msg) from None