Ypsilon.Tests.Run C# (CSharp) Method

Run() public static method

public static Run ( ) : string
return string
        public static string Run()
        {
            m_TestCount = 0;
            List<string> list = new List<string>();

            try
            {
                // test number formats
                Test("cmp r7, 1234", (ushort)(0x0007), 1234); // test non-hex numbers
                Test("cmp r7, $1234", (ushort)(0x0007), 0x1234); // test non-hex numbers
                Test("cmp r7, 0x1234", (ushort)(0x0007), 0x1234); // test non-hex numbers

                // test alu
                string[] alu_instructions = {
                    "cmp", "neg", "add", "sub", "adc", "sbc", "mul", "div",
                    "mli", "dvi", "mod", "mdi", "and", "orr", "eor", "not",
                    "lod", "sto" };
                ushort[] alu_codes = {
                    0x0000, 0x0008, 0x0010, 0x0018, 0x0020, 0x0028, 0x0030, 0x0038,
                    0x0040, 0x0048, 0x0050, 0x0058, 0x0060, 0x0068, 0x0070, 0x0078,
                    0x0080, 0x0088 };
                string[] reg_control = { "fl", "pc", "ps", string.Empty, string.Empty, string.Empty, "usp", "sp" };

                for (int ins = 0; ins < alu_instructions.Length; ins++)
                {
                    for (int r0 = 0; r0 < 8; r0++)
                    {
                        if (alu_instructions[ins] != "sto")
                        {
                            Test($"{alu_instructions[ins]}     r{r0}, $1234", (ushort)(0x0000 | alu_codes[ins] | r0), 0x1234);
                            Test($"{alu_instructions[ins]}.8   r{r0}, $0034", (ushort)(0x0100 | alu_codes[ins] | r0), 0x0034);
                        }
                        Test($"{alu_instructions[ins]}     r{r0}, [$1234]", (ushort)(0x0200 | alu_codes[ins] | r0), 0x1234);
                        Test($"{alu_instructions[ins]}     r{r0}, ES[$1234]", (ushort)(0x8200 | alu_codes[ins] | r0), 0x1234);
                        Test($"{alu_instructions[ins]}.8   r{r0}, [$1234]", (ushort)(0x0300 | alu_codes[ins] | r0), 0x1234);
                        Test($"{alu_instructions[ins]}.8   r{r0}, ES[$1234]", (ushort)(0x8300 | alu_codes[ins] | r0), 0x1234);
                        for (int cr = 0; cr < 8; cr++)
                        {
                            if (reg_control[cr] == string.Empty)
                                continue;
                            Test($"{alu_instructions[ins]}     r{r0}, {reg_control[cr]}", (ushort)(0x0800 | alu_codes[ins] | r0 | (cr << 8)));
                        }
                        for (int r1 = 0; r1 < 8; r1++)
                        {
                            if (alu_instructions[ins] != "sto")
                            {
                                Test($"{alu_instructions[ins]}     r{r0}, r{r1}", (ushort)(0x1000 | alu_codes[ins] | r0 | (r1 << 9)));
                                Test($"{alu_instructions[ins]}.8   r{r0}, r{r1}", (ushort)(0x1100 | alu_codes[ins] | r0 | (r1 << 9)));
                            }
                            Test($"{alu_instructions[ins]}     r{r0}, [r{r1}]", (ushort)(0x2000 | alu_codes[ins] | r0 | (r1 << 9)));
                            Test($"{alu_instructions[ins]}.8   r{r0}, [r{r1}]", (ushort)(0x2100 | alu_codes[ins] | r0 | (r1 << 9)));
                            Test($"{alu_instructions[ins]}     r{r0}, ES[r{r1}]", (ushort)(0xA000 | alu_codes[ins] | r0 | (r1 << 9)));
                            Test($"{alu_instructions[ins]}.8   r{r0}, ES[r{r1}]", (ushort)(0xA100 | alu_codes[ins] | r0 | (r1 << 9)));
                            Test($"{alu_instructions[ins]}     r{r0}, [r{r1},$1234]", (ushort)(0x3000 | alu_codes[ins] | r0 | (r1 << 9)), 0x1234);
                            Test($"{alu_instructions[ins]}.8   r{r0}, [r{r1},$1234]", (ushort)(0x3100 | alu_codes[ins] | r0 | (r1 << 9)), 0x1234);
                            Test($"{alu_instructions[ins]}     r{r0}, ES[r{r1},$1234]", (ushort)(0xB000 | alu_codes[ins] | r0 | (r1 << 9)), 0x1234);
                            Test($"{alu_instructions[ins]}.8   r{r0}, ES[r{r1},$1234]", (ushort)(0xB100 | alu_codes[ins] | r0 | (r1 << 9)), 0x1234);
                            for (int r2 = 4; r2 < 8; r2++)
                            {
                                Test($"{alu_instructions[ins]}     r{r0}, [r{r1},r{r2}]", (ushort)(0x4000 | alu_codes[ins] | r0 | (r1 << 9) | ((r2 - 4) << 12)));
                                Test($"{alu_instructions[ins]}.8   r{r0}, [r{r1},r{r2}]", (ushort)(0x4100 | alu_codes[ins] | r0 | (r1 << 9) | ((r2 - 4) << 12)));
                                Test($"{alu_instructions[ins]}     r{r0}, ES[r{r1},r{r2}]", (ushort)(0xC000 | alu_codes[ins] | r0 | (r1 << 9) | ((r2 - 4) << 12)));
                                Test($"{alu_instructions[ins]}.8   r{r0}, ES[r{r1},r{r2}]", (ushort)(0xC100 | alu_codes[ins] | r0 | (r1 << 9) | ((r2 - 4) << 12)));
                            }
                        }

                    }
                }

                // test branch
                string[] bra_instructions = {
                    "bcc", "bcs", "bne", "beq", "bpl", "bmi", "bvc", "bvs",
                    "bug", "bsg", "baw" };
                ushort[] bra_codes = {
                    0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
                    0x0098, 0x0099, 0x009F };

                for (int ins = 0; ins < bra_instructions.Length; ins++)
                {
                    for (int offset = sbyte.MinValue; offset <= sbyte.MaxValue; offset++)
                    {
                        Test($"{bra_instructions[ins]}     {offset}", (ushort)(bra_codes[ins] | ((byte)offset << 8)));
                    }
                }

                // test shift
                string[] shf_instructions = {
                    "asl", "lsl", "rol", "rnl",
                    "asr", "lsr", "ror", "rnr"
                };
                ushort[] shf_codes = {
                    0x00A0, 0x00A1, 0x00A2, 0x00A3,
                    0x00A4, 0x00A5, 0x00A6, 0x00A7
                };

                for (int ins = 0; ins < shf_instructions.Length; ins++)
                {
                    for (int r0 = 0; r0 < 8; r0++)
                    {
                        for (int offset = 1; offset <= 16; offset++)
                        {
                            Test($"{shf_instructions[ins]}     r{r0}, {offset}",
                                (ushort)(shf_codes[ins] | ((byte)(offset - 1) << 8) | 0x0000 | (r0 << 13)));
                        }

                        for (int r1 = 0; r1 < 8; r1++)
                        {
                            Test($"{shf_instructions[ins]}     r{r0}, r{r1}",
                                (ushort)(shf_codes[ins] | (r1 << 8) | 0x1000 | (r0 << 13)));
                        }
                    }
                }

                // test bit-testing, setting, clearing
                string[] bti_instructions = {
                    "btt", "btx", "btc", "bts"
                };
                ushort[] bti_codes = {
                    0x00A8, 0x00A9, 0x00AA, 0x00AB
                };

                for (int ins = 0; ins < bti_instructions.Length; ins++)
                {
                    for (int r0 = 0; r0 < 8; r0++)
                    {
                        for (int offset = 0; offset < 16; offset++)
                        {
                            Test($"{bti_instructions[ins]}     r{r0}, {offset}",
                                (ushort)(bti_codes[ins] | ((byte)(offset) << 8) | 0x0000 | (r0 << 13)));
                        }

                        for (int r1 = 0; r1 < 8; r1++)
                        {
                            Test($"{bti_instructions[ins]}     r{r0}, r{r1}",
                                (ushort)(bti_codes[ins] | (r1 << 8) | 0x1000 | (r0 << 13)));
                        }
                    }
                }

                // test set
                for (int v = 0; v < 0x20; v++)
                    for (int r = 0; r < 8; r++)
                        Test($"set     r{r}, {v}",
                            (ushort)(0x00AC | (v << 8) | (r << 13)));
                for (int v = 0; v < 0x20; v++)
                {
                    ushort v0 = (v <= 0x0A) ?
                            (ushort)Math.Pow(2, 5 + v) :
                            (ushort)(0xFFE0 + v);
                    for (int r = 0; r < 8; r++)
                    {
                        Test($"set     r{r}, {v0}",
                            (ushort)(0x00AD | (v << 8) | (r << 13)));
                    }
                }

                // test sef / clf
                for (int flg = 1; flg < 16; flg++)
                {
                    list.Clear();
                    if ((flg & 0x01) != 0)
                        list.Add("v");
                    if ((flg & 0x02) != 0)
                        list.Add("c");
                    if ((flg & 0x04) != 0)
                        list.Add("z");
                    if ((flg & 0x08) != 0)
                        list.Add("n");
                    string flg_str = list.Select(i => i).
                        Aggregate((i, j) => i + "," + j);
                    Test($"sef     {flg_str}",
                            (ushort)(0x00AE | (flg << 12)));
                    Test($"clf     {flg_str}",
                            (ushort)(0x00AF | (flg << 12)));
                }

                // test push / pop
                for (int stk = 1; stk < 256; stk++)
                {
                    list.Clear();
                    for (int i = 0; i < 8; i++)
                    {
                        int p = (int)Math.Pow(2, i);
                        if ((stk & p) == p)
                            list.Add($"r{i}");
                    }
                    string regs = list.Select(i => i).
                        Aggregate((i, j) => i + "," + j);
                    Test($"psh     {regs}",
                            (ushort)(0x00B0 | (stk << 8)));
                    Test($"pop     {regs}",
                            (ushort)(0x00B2 | (stk << 8)));
                }

                string[] stk_crs = {
                    "fl", "pc", "ps", string.Empty, string.Empty, string.Empty, "usp", "sp" };
                for (int stk = 1; stk < 256; stk++)
                {
                    list.Clear();
                    for (int i = 0; i < 8; i++)
                    {
                        int p = (int)Math.Pow(2, i);
                        if ((stk & p) == p)
                        {
                            if (stk_crs[i] == string.Empty)
                                goto notThisReg;
                            list.Add(stk_crs[i]);
                        }
                    }
                    string regs = list.Select(i => i).
                        Aggregate((i, j) => i + "," + j);
                    Test($"psh     {regs}",
                            (ushort)(0x00B1 | (stk << 8)));
                    Test($"pop     {regs}",
                            (ushort)(0x00B3 | (stk << 8)));
                notThisReg:;
                }

                // test rts / rts.f / slp / swi / rti
                Test("rts", 0x00B4);
                Test("rts.f", 0x01B4);
                Test("rti", 0x02B4);
                Test("swi", 0x03B4);
                Test("slp", 0x04B4);

                // test lsg / ssg
                string[] mmu_instructions = { "lsg", "ssg" };
                ushort[] mmu_codes = { 0x00B5, 0x01B5 };
                string[] seg_regs = { "cs", "ds", "es", "ss" };

                for (int ins = 0; ins < mmu_instructions.Length; ins++)
                {
                    for (int sr = 0; sr < seg_regs.Length; sr++)
                    {
                        Test($"{mmu_instructions[ins]}     {seg_regs[sr]}s",
                            (ushort)(0x0000 | mmu_codes[ins] | (sr << 9)));
                        Test($"{mmu_instructions[ins]}     {seg_regs[sr]}u",
                            (ushort)(0x8000 | mmu_codes[ins] | (sr << 9)));
                    }
                    Test($"{mmu_instructions[ins]}     is",
                            (ushort)(0x0800 | mmu_codes[ins]));
                }

                // test inc / adi / dec / sbi
                for (int r = 0; r < 8; r++)
                {
                    Test($"inc r{r}",
                        (ushort)(0x00B6 | (r << 13)));
                    Test($"dec r{r}",
                        (ushort)(0x00B7 | (r << 13)));

                    for (int imm = 1; imm <= 0x20; imm++)
                    {
                        Test($"adi r{r}, {imm}",
                        (ushort)(0x00B6 | (r << 13) | ((imm - 1) << 8)));
                        Test($"sbi r{r}, {imm}",
                            (ushort)(0x00B7 | (r << 13) | ((imm - 1) << 8)));
                    }
                }

                // test jmp / jsr
                string[] jmi_instructions = { "jmp", "jsr" };
                ushort[] jmi_codes = { 0x00B8, 0x00B9 };

                for (int ins = 0; ins < jmi_instructions.Length; ins++)
                {
                    Test($"{jmi_instructions[ins]}     $1234",
                        (ushort)(0x0000 | jmi_codes[ins]), 0x1234);
                    Test($"{jmi_instructions[ins]}.f   $1234, $56789abc",
                        (ushort)(0x0100 | jmi_codes[ins]), 0x1234, 0x9abc, 0x5678);
                    Test($"{jmi_instructions[ins]}     [$1234]",
                        (ushort)(0x0200 | jmi_codes[ins]), 0x1234);
                    Test($"{jmi_instructions[ins]}     ES[$1234]",
                        (ushort)(0x8200 | jmi_codes[ins]), 0x1234);
                    Test($"{jmi_instructions[ins]}.f   [$1234]",
                        (ushort)(0x0300 | jmi_codes[ins]), 0x1234);
                    Test($"{jmi_instructions[ins]}.f   ES[$1234]",
                        (ushort)(0x8300 | jmi_codes[ins]), 0x1234);

                    for (int r1 = 0; r1 < 8; r1++)
                    {
                        // register
                        Test($"{jmi_instructions[ins]}     r{r1}",
                            (ushort)(0x1000 | jmi_codes[ins] | (r1 << 9)));
                        // indirect
                        Test($"{jmi_instructions[ins]}     [r{r1}]",
                            (ushort)(0x2000 | jmi_codes[ins] | (r1 << 9)));
                        Test($"{jmi_instructions[ins]}.f   [r{r1}]",
                            (ushort)(0x2100 | jmi_codes[ins] | (r1 << 9)));
                        Test($"{jmi_instructions[ins]}     ES[r{r1}]",
                            (ushort)(0xA000 | jmi_codes[ins] | (r1 << 9)));
                        Test($"{jmi_instructions[ins]}.f   ES[r{r1}]",
                            (ushort)(0xA100 | jmi_codes[ins] | (r1 << 9)));
                        // indirect offset
                        Test($"{jmi_instructions[ins]}     [r{r1},$1234]",
                            (ushort)(0x3000 | jmi_codes[ins] | (r1 << 9)), 0x1234);
                        Test($"{jmi_instructions[ins]}.f   [r{r1},$1234]",
                            (ushort)(0x3100 | jmi_codes[ins] | (r1 << 9)), 0x1234);
                        Test($"{jmi_instructions[ins]}     ES[r{r1},$1234]",
                            (ushort)(0xB000 | jmi_codes[ins] | (r1 << 9)), 0x1234);
                        Test($"{jmi_instructions[ins]}.f   ES[r{r1},$1234]",
                            (ushort)(0xB100 | jmi_codes[ins] | (r1 << 9)), 0x1234);
                        // indirect indexed
                        for (int r2 = 4; r2 < 8; r2++)
                        {
                            Test($"{jmi_instructions[ins]}     [r{r1},r{r2}]",
                                (ushort)(0x4000 | jmi_codes[ins] | (r1 << 9) | ((r2 - 4) << 12)));
                            Test($"{jmi_instructions[ins]}.f   [r{r1},r{r2}]",
                                (ushort)(0x4100 | jmi_codes[ins] | (r1 << 9) | ((r2 - 4) << 12)));
                            Test($"{jmi_instructions[ins]}     ES[r{r1},r{r2}]",
                                (ushort)(0xC000 | jmi_codes[ins] | (r1 << 9) | ((r2 - 4) << 12)));
                            Test($"{jmi_instructions[ins]}.f   ES[r{r1},r{r2}]",
                                (ushort)(0xC100 | jmi_codes[ins] | (r1 << 9) | ((r2 - 4) << 12)));
                        }
                    }
                }

                // test hwq
                for (int i = 0; i < 256; i++)
                    Test($"hwq {i}",
                        (ushort)(0x00BA | (i << 8)));

                // test stx
                for (int i = sbyte.MinValue; i <= sbyte.MaxValue; i++)
                    Test($"stx {i}",
                        (ushort)(0x00BB | (((sbyte)i) << 8)));

            }
            catch (Exception e)
            {
                return e.Message;
            }

            return $"Test successful! {m_TestCount} tests completed";
        }