503 lines · 16.9 KB · Python
RawDownload
"""Copyright (C) 2017 David Boddie <david@boddie.org.uk> This program is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details. You should have received a copy of the GNU General Public Licensealong with this program.  If not, see <http://www.gnu.org/licenses/>.""" # See http://inferno-os.org/inferno/papers/dis.html or#     http://doc.cat-v.org/inferno/4th_edition/dis_VM_specification# for information. from utils import read_B, read_OP, write_B, write_OP class Instruction:     def __init__(self):            self.source = NoOperand()        self.middle = NoOperand()        self.destination = NoOperand()        self.set_address_mode()        def read(self, f):            opcode = read_B(f)        class_ = instructions[opcode]                address_mode = read_B(f)                middle = address_mode & 0xc0        middle = self.read_middle_operand(middle, f)                source = (address_mode & 0x38) >> 3        source = self.read_operand(source, f)                destination = address_mode & 0x07        destination = self.read_operand(destination, f)                if issubclass(class_, Src):            return class_(source)        elif issubclass(class_, Src_Src):            return class_(source, middle)        elif issubclass(class_, Src_Dst):            return class_(source, destination)        elif issubclass(class_, Src_Src_Dst):            return class_(source, middle, destination)        elif issubclass(class_, Src_Src_Src):            return class_(source, middle, destination)        elif issubclass(class_, Dst):            return class_(destination)        else:            return class_()        def set_address_mode(self):            self.address_mode = self.middle.middle_address_mode | \                            (self.source.address_mode << 3) | \                            self.destination.address_mode        def read_operand(self, operand, f):            # Since we shift the address flags for the source operand, we can        # check both source and destination operands using the same values.                if operand == 0x00:            operand = LongOffsetMP(read_OP(f), "LO(MP)")        elif operand == 0x01:            operand = LongOffsetFP(read_OP(f), "LO(FP)")        elif operand == 0x02:            operand = Immediate(read_OP(f), "$OP")                # No operand for 0x03.                elif operand == 0x04:            inner, outer = read_OP(f), read_OP(f)            operand = DoubleShortOffsetMP(outer, inner, "SO(SO(MP))")        elif operand == 0x05:            inner, outer = read_OP(f), read_OP(f)            operand = DoubleShortOffsetFP(outer, inner, "SO(SO(FP))")        else:            operand = NoOperand()                return operand        def read_middle_operand(self, operand, f):            # The middle operand bits are not shifted.                if operand == 0x40:            operand = Immediate(read_OP(f), "$SI")        elif operand == 0x80:            operand = ShortOffsetFP(read_OP(f), "SO(FP)")        elif operand == 0xc0:            operand = ShortOffsetMP(read_OP(f), "SO(MP)")        else:            operand = NoOperand()                return operand        def write(self, f):            write_B(f, self.opcode)        write_B(f, self.address_mode)                self.middle.write(f)        self.source.write(f)        self.destination.write(f)        def __repr__(self):            try:            name = self.__class__.__name__        except IndexError:            name = hex(self.opcode)                operands = []                for operand in self.source, self.middle, self.destination:            s = str(operand)            if s:                operands.append(s)                return name + " " + ", ".join(operands)  # Define the argument types. class NoOperand:     middle_address_mode = 0x00    address_mode = 0x03        def write(self, f):        pass        def __str__(self):        return "" class Operand:     def __init__(self, value, annotation = None):            self.value = value        self.annotation = annotation        def __str__(self):        return self.str_pattern % self.value        def write(self, f):        write_OP(f, self.value) class Immediate(Operand):    str_pattern = "$0x%x"    middle_address_mode = 0x40    address_mode = 0x02 class LongOffset(Operand):    pass class LongOffsetMP(LongOffset):    str_pattern = "%i(mp)"    address_mode = 0x00 class LongOffsetFP(LongOffset):    str_pattern = "%i(fp)"    address_mode = 0x01 class ShortOffset(Operand):    pass class ShortOffsetMP(ShortOffset):    str_pattern = "%i(mp)"    middle_address_mode = 0xc0 class ShortOffsetFP(ShortOffset):    str_pattern = "%i(fp)"    middle_address_mode = 0x80 class DoubleShortOffset(Operand):     def __init__(self, outer, inner, annotation = None):            self.offset0 = inner        self.offset1 = outer        self.annotation = annotation        def __str__(self):        return self.str_pattern % (self.offset1, self.offset0)        def write(self, f):        write_OP(f, self.offset0 & 0xffff)        write_OP(f, self.offset1 & 0xffff) class DoubleShortOffsetMP(DoubleShortOffset):    str_pattern = "%i(%i(mp))"    address_mode = 0x04 class DoubleShortOffsetFP(DoubleShortOffset):    str_pattern = "%i(%i(fp))"    address_mode = 0x05 Imm = ImmediateLOfp = LongOffsetFPLOmp = LongOffsetMPNoOp = NoOperandSOfp = ShortOffsetFPSOmp = ShortOffsetMPSOSOfp = DoubleShortOffsetFPSOSOmp = DoubleShortOffsetMP # Define the instructions and their opcode values. class Src(Instruction):        def __init__(self, src):            self.source = src        self.middle = NoOperand()        self.destination = NoOperand()        self.set_address_mode() class Src_Dst(Instruction):        def __init__(self, src, dst):            self.source = src        self.middle = NoOperand()        self.destination = dst        self.set_address_mode() class Src_Src(Instruction):        def __init__(self, src1, src2):            self.source = src1        self.middle = src2        self.destination = NoOperand()        self.set_address_mode() class Src_Src_Dst(Instruction):     def __init__(self, src1, src2, dst):            self.source = src1        self.middle = src2        self.destination = dst        self.set_address_mode() class Src_Src_Src(Instruction):     def __init__(self, src1, src2, src3):            self.source = src1        self.middle = src2        self.destination = src3        self.set_address_mode() class Dst(Instruction):        def __init__(self, dst):            self.source = NoOperand()        self.middle = NoOperand()        self.destination = dst        self.set_address_mode() # Groups of instructionsclass addx(Src_Src_Dst):  passclass andx(Src_Src_Dst):  passclass beqx(Src_Src_Dst):  passclass bgex(Src_Src_Dst):  passclass bgtx(Src_Src_Dst):  passclass blex(Src_Src_Dst):  passclass bltx(Src_Src_Dst):  passclass bnex(Src_Src_Dst):  passclass consx(Src_Dst):     passclass divx_(Src_Src_Dst): passclass headx(Src_Dst):     passclass indx_(Src_Src_Dst): passclass lsrx(Src_Src_Dst):  passclass modx(Src_Src_Dst):  passclass movx(Src_Dst):      passclass mulx_(Src_Src_Dst): passclass newcx(Dst):         passclass orx(Src_Src_Dst):   passclass shlx(Src_Src_Dst):  passclass shrx(Src_Src_Dst):  passclass subx(Src_Src_Dst):  passclass xorx(Src_Src_Dst):  pass # Individual definitions (marked with the file in libinterp with information)class addb(addx):           opcode = 0x39class addc(addx):           opcode = 0x53class addf(addx):           opcode = 0x3bclass addl(addx):           opcode = 0x77class addw(addx):           opcode = 0x3aclass alt(Src_Dst):         opcode = 0x01class andb(andx):           opcode = 0x47class andl(andx):           opcode = 0x7cclass andw(andx):           opcode = 0x48class beqb(beqx):           opcode = 0x57class beqc(beqx):           opcode = 0x69class beqf(beqx):           opcode = 0x63class beql(beqx):           opcode = 0x86class beqw(beqx):           opcode = 0x5dclass bgeb(bgex):           opcode = 0x5cclass bgec(bgex):           opcode = 0x6eclass bgef(bgex):           opcode = 0x68class bgel(bgex):           opcode = 0x85class bgew(bgex):           opcode = 0x62class bgtb(bgtx):           opcode = 0x5bclass bgtc(bgtx):           opcode = 0x6dclass bgtf(bgtx):           opcode = 0x67class bgtl(bgtx):           opcode = 0x84class bgtw(bgtx):           opcode = 0x61class bleb(blex):           opcode = 0x5aclass blec(blex):           opcode = 0x6cclass blef(blex):           opcode = 0x66class blel(blex):           opcode = 0x83class blew(blex):           opcode = 0x60class bltb(bltx):           opcode = 0x59class bltc(bltx):           opcode = 0x6bclass bltf(bltx):           opcode = 0x65class bltl(bltx):           opcode = 0x82class bltw(bltx):           opcode = 0x5fclass bneb(bnex):           opcode = 0x58class bnec(bnex):           opcode = 0x6aclass bnef(bnex):           opcode = 0x64class bnel(bnex):           opcode = 0x81class bnew(bnex):           opcode = 0x5eclass call(Src_Dst):        opcode = 0x04class case(Src_Dst):        opcode = 0x0eclass casec(Src_Dst):       opcode = 0x90class casel(Src_Dst):       opcode = 0x9f   ### check syntaxclass consb(consx):         opcode = 0x1aclass consf(consx):         opcode = 0x1dclass consl(consx):         opcode = 0x8eclass consm(consx):         opcode = 0x1eclass consmp(consx):        opcode = 0x1fclass consp(consx):         opcode = 0x1cclass consw(consx):         opcode = 0x1bclass cvtac(Src_Dst):       opcode = 0x34class cvtbw(Src_Dst):       opcode = 0x2fclass cvtca(Src_Dst):       opcode = 0x33class cvtcf(Src_Dst):       opcode = 0x38class cvtcl(Src_Dst):       opcode = 0x8cclass cvtcw(Src_Dst):       opcode = 0x36class cvtfc(Src_Dst):       opcode = 0x37class cvtfl(Src_Dst):       opcode = 0x88class cvtfr(Src_Dst):       opcode = 0x96class cvtfw(Src_Dst):       opcode = 0x31class cvtfx(Src_Dst):       opcode = 0xa9class cvtlc(Src_Dst):       opcode = 0x8bclass cvtlf(Src_Dst):       opcode = 0x87class cvtlw(Src_Dst):       opcode = 0x89class cvtrf(Src_Dst):       opcode = 0x95class cvtsw(Src_Dst):       opcode = 0x98   # short to word (xec.c)class cvtwb(Src_Dst):       opcode = 0x30   # word to byte (xec.c)class cvtwc(Src_Dst):       opcode = 0x35   # word to char array (string.c)class cvtwf(Src_Dst):       opcode = 0x32   # word to float (xec.c)class cvtwl(Src_Dst):       opcode = 0x8a   # word to long (xec.c)class cvtws(Src_Dst):       opcode = 0x97   # word to short (xec.c)class cvtxf(Src_Src_Dst):   opcode = 0xaa   # word * float -> float (xec.c)class cvtxx0(Src_Src_Dst):  opcode = 0xa5   ### word ? word -> word (xec.c)class cvtxx1(Src_Src_Dst):  opcode = 0xa8   ### word ? word -> word (xec.c)class cvtxx(Src_Src_Dst):   opcode = 0xa2   ### word ? word -> word (xec.c)class divb(divx_):          opcode = 0x42class divf(divx_):          opcode = 0x44class divl(divx_):          opcode = 0x79class divw(divx_):          opcode = 0x43class divx0(divx_):         opcode = 0xa4   # (xec.c)class divx1(divx_):         opcode = 0xa7   # (xec.c)class divx(divx_):          opcode = 0xa1   # (xec.c)class eclr(Instruction):    opcode = 0x9b   # unusedclass exit(Instruction):    opcode = 0x0fclass expf(Src_Src_Dst):    opcode = 0xad   # word word -> float (xec.c)class expl(Src_Src_Dst):    opcode = 0xac   # word long -> long (xec.c)class expw(Src_Src_Dst):    opcode = 0xab   # word word -> word (xec.c)class frame(Src_Dst):       opcode = 0x05   # not src1, src2 as in documentationclass goto(Src_Dst):        opcode = 0x03class headb(headx):         opcode = 0x20class headf(headx):         opcode = 0x23class headl(headx):         opcode = 0x8dclass headm(headx):         opcode = 0x24class headmp(headx):        opcode = 0x25class headp(headx):         opcode = 0x22class headw(headx):         opcode = 0x21class indb(indx_):          opcode = 0x74class indc(Src_Src_Dst):    opcode = 0x52class indf(indx_):          opcode = 0x73class indl(indx_):          opcode = 0x91class indw(indx_):          opcode = 0x72class indx(Src_Src_Dst):    opcode = 0x28class insc(Src_Src_Dst):    opcode = 0x51class jmp(Dst):             opcode = 0x0dclass lea(Src_Dst):         opcode = 0x27class lena(Src_Dst):        opcode = 0x55class lenc(Src_Dst):        opcode = 0x54class lenl(Src_Dst):        opcode = 0x56class load(Src_Src_Dst):    opcode = 0x08class lsrl(lsrx):           opcode = 0x9aclass lsrw(lsrx):           opcode = 0x99class mcall(Src_Src_Src):   opcode = 0x09class mframe(Src_Src_Dst):  opcode = 0x0bclass mnewz(Src_Src_Dst):   opcode = 0x94class modb(modx):           opcode = 0x46class modl(modx):           opcode = 0x7aclass modw(modx):           opcode = 0x45class movb(movx):           opcode = 0x2cclass movf(movx):           opcode = 0x2eclass movl(movx):           opcode = 0x76class movm(Src_Src_Dst):    opcode = 0x2aclass movmp(Src_Src_Dst):   opcode = 0x2bclass movpc(Src_Dst):       opcode = 0x92class movp(Src_Dst):        opcode = 0x29class movw(movx):           opcode = 0x2dclass mspawn(Src_Src_Src):  opcode = 0x0aclass mulb(mulx_):          opcode = 0x3fclass mulf(mulx_):          opcode = 0x41class mull(mulx_):          opcode = 0x7bclass mulw(mulx_):          opcode = 0x40class mulx0(mulx_):         opcode = 0xa3   ### word * word -> word (xec.c)class mulx1(mulx_):         opcode = 0xa6   ### word * word -> word (xec.c)class mulx(mulx_):          opcode = 0xa0   ### word * word -> word (xec.c)class nbalt(Src_Dst):       opcode = 0x02class negf(Src_Dst):        opcode = 0x75class new(Src_Dst):         opcode = 0x10class newa(Src_Src_Dst):    opcode = 0x11class newaz(Src_Src_Dst):   opcode = 0x9dclass newcb(newcx):         opcode = 0x12class newcf(newcx):         opcode = 0x14class newcl(newcx):         opcode = 0x8fclass newcm(newcx):         opcode = 0x16class newcmp(newcx):        opcode = 0x17class newcp(newcx):         opcode = 0x15class newcw(newcx):         opcode = 0x13class newz(Src_Dst):        opcode = 0x9cclass nop(Instruction):     opcode = 0x00class orb(orx):             opcode = 0x49class orl(orx):             opcode = 0x7dclass orw(orx):             opcode = 0x4aclass raise_(Src):          opcode = 0x9e   ### type (xec.c)class recv(Src_Dst):        opcode = 0x19class ret(Instruction):     opcode = 0x0cclass runt(Instruction):    opcode = 0x07   ### no operands (xec.c)class self(Instruction):    opcode = 0xae   ### no operands? (xec.c)class send(Src_Dst):        opcode = 0x18class shlb(shlx):           opcode = 0x4dclass shll(shlx):           opcode = 0x7fclass shlw(shlx):           opcode = 0x4eclass shrb(shrx):           opcode = 0x4fclass shrl(shrx):           opcode = 0x80class shrw(shrx):           opcode = 0x50class slicea(Src_Src_Dst):  opcode = 0x6fclass slicec(Src_Src_Dst):  opcode = 0x71class slicela(Src_Src_Dst): opcode = 0x70class spawn(Src_Dst):       opcode = 0x06class subb(subx):           opcode = 0x3cclass subf(subx):           opcode = 0x3eclass subl(subx):           opcode = 0x78class subw(subx):           opcode = 0x3dclass tail(Src_Dst):        opcode = 0x26class tcmp(Src_Dst):        opcode = 0x93class xorb(xorx):           opcode = 0x4bclass xorl(xorx):           opcode = 0x7eclass xorw(xorx):           opcode = 0x4c # Define a list to map opcodes to instruction classes. instructions = [    nop, alt, nbalt, goto, call, frame, spawn, runt,    load, mcall, mspawn, mframe, ret, jmp, case, exit,    new, newa, newcb, newcw, newcf, newcp, newcm, newcmp,    send, recv, consb, consw, consp, consf, consm, consmp,    headb, headw, headp, headf, headm, headmp, tail, lea,    indx, movp, movm, movmp, movb, movw, movf, cvtbw,    cvtwb, cvtfw, cvtwf, cvtca, cvtac, cvtwc, cvtcw, cvtfc,    cvtcf, addb, addw, addf, subb, subw, subf, mulb,    mulw, mulf, divb, divw, divf, modw, modb, andb,    andw, orb, orw, xorb, xorw, shlb, shlw, shrb,    shrw, insc, indc, addc, lenc, lena, lenl, beqb,    bneb, bltb, bleb, bgtb, bgeb, beqw, bnew, bltw,    blew, bgtw, bgew, beqf, bnef, bltf, blef, bgtf,    bgef, beqc, bnec, bltc, blec, bgtc, bgec, slicea,    slicela, slicec, indw, indf, indb, negf, movl, addl,    subl, divl, modl, mull, andl, orl, xorl, shll,    shrl, bnel, bltl, blel, bgtl, bgel, beql, cvtlf,    cvtfl, cvtlw, cvtwl, cvtlc, cvtcl, headl, consl, newcl,    casec, indl, movpc, tcmp, mnewz, cvtrf, cvtfr, cvtws,    cvtsw, lsrw, lsrl, eclr, newz, newaz, raise_, casel,

Lines 1–500 of 503.