Пример #1
0
        public static AssemblerResult StaticAssembleInstructions(string program)
        {
            var memory = new MemoryStream();
            var result = new AssemblerResult
            {
                Instructions = new StreamStructArrayWrapper <Instruction>(memory),
            };
            var mipsAssembler = new MipsAssembler(memory);

            mipsAssembler.Assemble(program, result);
            return(result);
        }
Пример #2
0
        /* Format codes
         * %d - Rd
         * %t - Rt
         * %s - Rs
         * %i - 16bit signed immediate
         * %I - 16bit unsigned immediate (always printed in hex)
         * %o - 16bit signed offset (rs base)
         * %O - 16bit signed offset (PC relative)
         * %j - 26bit absolute offset
         * %J - Register jump
         * %a - SA
         * %0 - Cop0 register
         * %1 - Cop1 register
         * %2? - Cop2 register (? is (s, d))
         * %p - General cop (i.e. numbered) register
         * %n? - ins/ext size, ? (e, i)
         * %r - Debug register
         * %k - Cache function
         * %D - Fd
         * %T - Ft
         * %S - Fs
         * %x? - Vt (? is (s/scalar, p/pair, t/triple, q/quad, m/matrix pair, n/matrix triple, o/matrix quad)
         * %y? - Vs
         * %z? - Vd
         * %X? - Vo (? is (s, q))
         * %Y - VFPU offset
         * %Z? - VFPU condition code/name (? is (c, n))
         * %v? - VFPU immediate, ? (3, 5, 8, k, i, h, r, p? (? is (0, 1, 2, 3, 4, 5, 6, 7)))
         * %c - code (for break)
         * %C - code (for syscall)
         * %? - Indicates vmmul special exception
         */

        public void Assemble(string lines, AssemblerResult assemblerResult = null)
        {
            if (assemblerResult == null)
            {
                assemblerResult = new AssemblerResult();
            }

            var labels  = assemblerResult.Labels;
            var patches = assemblerResult.Patches;

            foreach (var line in lines.Split('\n').Select(str => str.Trim()).Where(str => str.Length > 0))
            {
                // Strip comments.
                var parts    = line.Split(new[] { ";", "#" }, 2, StringSplitOptions.None);
                var realLine = parts[0].Trim();

                // Directive
                if (line[0] == '.')
                {
                    var lineTokens = line.Split(new[] { ' ', '\t' }, 2);
                    switch (lineTokens[0])
                    {
                    case ".code":
                        OutputStream.Position = ParseIntegerConstant(lineTokens[1]);
                        break;

                    default:
                        throw new NotImplementedException("Unsupported directive '" + lineTokens[0] + "'");
                    }
                }
                else
                {
                    // Label
                    if (realLine.EndsWith(":"))
                    {
                        labels[realLine.Substr(0, -1).Trim()] = (uint)OutputStream.Position;
                    }
                    // Instruction
                    else
                    {
                        var pc           = (uint)OutputStream.Position;
                        var instructions = AssembleInstructions(ref pc, realLine, patches);
                        foreach (var instruction in instructions)
                        {
                            BinaryWriter.Write(instruction.Value);
                        }
                    }
                }
            }

            foreach (var patch in patches)
            {
                if (!labels.ContainsKey(patch.LabelName))
                {
                    throw new KeyNotFoundException($"Can't find label '{patch.LabelName}'");
                }

                var labelAddress = labels[patch.LabelName];

                OutputStream.Position = patch.Address;
                var instruction = (Instruction)BinaryReader.ReadUInt32();
                {
                    switch (patch.Type)
                    {
                    case AssemblerPatchType.Rel16:
                        instruction.Imm = ((int)labelAddress - (int)patch.Address - 4) / 4;
                        break;

                    case AssemblerPatchType.Abs26:
                        instruction.JumpBits = (labelAddress & PspMemory.MemoryMask) / 4;
                        Console.Write("0x{0:X} : {1}", instruction.JumpBits, patch.LabelName);
                        break;

                    case AssemblerPatchType.Abs32:
                        instruction.Value = labelAddress;
                        break;
                    }
                }
                OutputStream.Position = patch.Address;
                BinaryWriter.Write(instruction.Value);
            }
        }
Пример #3
0
        /* Format codes
         * %d - Rd
         * %t - Rt
         * %s - Rs
         * %i - 16bit signed immediate
         * %I - 16bit unsigned immediate (always printed in hex)
         * %o - 16bit signed offset (rs base)
         * %O - 16bit signed offset (PC relative)
         * %j - 26bit absolute offset
         * %J - Register jump
         * %a - SA
         * %0 - Cop0 register
         * %1 - Cop1 register
         * %2? - Cop2 register (? is (s, d))
         * %p - General cop (i.e. numbered) register
         * %n? - ins/ext size, ? (e, i)
         * %r - Debug register
         * %k - Cache function
         * %D - Fd
         * %T - Ft
         * %S - Fs
         * %x? - Vt (? is (s/scalar, p/pair, t/triple, q/quad, m/matrix pair, n/matrix triple, o/matrix quad)
         * %y? - Vs
         * %z? - Vd
         * %X? - Vo (? is (s, q))
         * %Y - VFPU offset
         * %Z? - VFPU condition code/name (? is (c, n))
         * %v? - VFPU immediate, ? (3, 5, 8, k, i, h, r, p? (? is (0, 1, 2, 3, 4, 5, 6, 7)))
         * %c - code (for break)
         * %C - code (for syscall)
         * %? - Indicates vmmul special exception
         */
        public void Assemble(String Lines, AssemblerResult AssemblerResult = null)
        {
            if (AssemblerResult == null) AssemblerResult = new AssemblerResult();

            var Labels = AssemblerResult.Labels;
            var Patches = AssemblerResult.Patches;

            foreach (var Line in Lines.Split(new char[] { '\n' }).Select(Str => Str.Trim()).Where(Str => Str.Length > 0))
            {
                // Strip comments.
                var Parts = Line.Split(new string[] { ";", "#" }, 2, StringSplitOptions.None);
                var RealLine = Parts[0].Trim();

                // Directive
                if (Line[0] == '.')
                {
                    var LineTokens = Line.Split(new char[] { ' ', '\t' }, 2);
                    switch (LineTokens[0])
                    {
                        case ".code":
                            OutputStream.Position = ParseIntegerConstant(LineTokens[1]);
                            break;
                        default:
                            throw (new NotImplementedException("Unsupported directive '" + LineTokens[0] + "'"));
                    }
                }
                else
                {
                    // Label
                    if (RealLine.EndsWith(":"))
                    {
                        Labels[RealLine.Substr(0, -1).Trim()] = (uint)OutputStream.Position;
                    }
                    // Instruction
                    else
                    {
                        uint PC = (uint)OutputStream.Position;
                        var Instructions = AssembleInstructions(ref PC, RealLine, Patches);
                        foreach (var Instruction in Instructions)
                        {
                            BinaryWriter.Write(Instruction.Value);
                        }
                    }
                }
            }

            foreach (var Patch in Patches)
            {
                if (Labels.ContainsKey(Patch.LabelName))
                {
                    var LabelAddress = Labels[Patch.LabelName];
                    Instruction Instruction;

                    OutputStream.Position = Patch.Address;
                    Instruction = (Instruction)BinaryReader.ReadUInt32();
                    {
                        switch (Patch.Type)
                        {
                            case AssemblerPatchType.REL_16:
                                Instruction.IMM = ((int)LabelAddress - (int)Patch.Address - 4) / 4;
                                break;
                            case AssemblerPatchType.ABS_26:
                                Instruction.JUMP_Bits = (LabelAddress & PspMemory.MemoryMask) / 4;
                                Console.Write("0x{0:X} : {1}", Instruction.JUMP_Bits, Patch.LabelName);
                                break;
                            case AssemblerPatchType.ABS_32:
                                Instruction.Value = LabelAddress;
                                break;
                        }
                    }
                    OutputStream.Position = Patch.Address; BinaryWriter.Write(Instruction.Value);
                }
                else
                {
                    throw(new KeyNotFoundException("Can't find label '" + Patch.LabelName + "'"));
                }
            }
        }
Пример #4
0
 public static AssemblerResult StaticAssembleInstructions(string Program)
 {
     var Memory = new MemoryStream();
     var Result = new AssemblerResult()
     {
         Instructions = new StreamStructArrayWrapper<Instruction>(Memory),
     };
     var MipsAssembler = new MipsAssembler(Memory);
     MipsAssembler.Assemble(Program, Result);
     return Result;
 }