// compile compiles the given AST and returns a CPU instance ready to run the code. func (t *Test) compile(ast *dp.AST) (c *cpu.CPU, err error) { var bin []cpu.Word if bin, t.dbg, err = asm.Assemble(ast); err != nil { return } if !hasExit(bin) { return nil, errors.New(fmt.Sprintf( "%s: Program has no unconditional EXIT. This means the test will run indefinitely.", t.file)) } t.profile = prof.New(bin, t.dbg) c = cpu.New() copy(c.Store.Mem[:], bin) c.ClockSpeed = time.Duration(time.Duration(*clock)) c.Trace = func(pc, op, a, b cpu.Word, s *cpu.Storage) { t.parseInstruction(pc, op, a, b, s, *trace) } c.InstructionHandler = func(pc cpu.Word, s *cpu.Storage) { t.profile.Update(pc, s) } c.NotifyBranchSkip = func(pc, cost cpu.Word) { t.profile.UpdateCost(pc, cost) } return }
func parseArgs() *cpu.CPU { flag.Usage = usage version := flag.Bool("version", false, "Display version information.") flag.Parse() if *version { fmt.Printf("%s\n", Version()) os.Exit(0) } if *scale < 1 { *scale = 1 } switch *display { case "lem1802", "sped3": default: fmt.Fprintf(os.Stderr, "Invalid display hardware name. Want: 'lem1802' or 'sped3'.\n") os.Exit(1) } var arg string if flag.NArg() == 0 { arg = "." } else { arg = flag.Arg(0) } targets := path.Expand(arg) if len(targets) == 0 { fmt.Fprintf(os.Stderr, "Invalid target path: %q\n", arg) os.Exit(1) } // Create the CPU. c := cpu.New() c.ClockSpeed = time.Millisecond / 100 err := Build(targets[0], c) if err != nil { fmt.Fprintf(os.Stderr, "Load binary: %s.\n", err) os.Exit(1) } // Bind all hardware. c.RegisterDevice(clock.New) c.RegisterDevice(lem1802.New) c.RegisterDevice(keyboard.New) c.RegisterDevice(m35fd.New) c.RegisterDevice(sped3.New) c.RegisterDevice(spc2000.New) c.RegisterDevice(etcp.New) // Load floppy disk if necessary. if len(*fdd) > 0 { err := insertFdd(c, *fdd, *fddReadOnly) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) } } return c }