// parseFile parses the provided file into a slice of instructions. func parseFile(filePath string) (insts []interface{}, err error) { f, err := os.Open(filePath) if err != nil { return nil, err } defer f.Close() var buf uint16 insts = make([]interface{}, 0) for { err = binary.Read(f, binary.BigEndian, &buf) if err != nil { if err == io.EOF { break } return nil, err } inst, err := op.Decode(buf) if err != nil { return nil, err } insts = append(insts, inst) } return insts, nil }
// Step decodes and executes one instruction. func (sys *System) Step() (err error) { if !sys.running { return ErrHalted } buf, err := sys.FetchInst() if err != nil { return err } inst, err := op.Decode(buf) if err != nil { return err } return sys.Exec(inst) }
// String returns pretty-printed memory and register information about the // system. func (sys *System) String() string { // TODO(u): Clean up this mess :) b := new(bytes.Buffer) fmt.Fprintln(b, "=== [ system information ] ===") fmt.Fprintln(b) fmt.Fprintln(b, "--- [ registers ] ---") fmt.Fprintln(b) fmt.Fprintf(b, "PC = %02X (%d)\n", sys.PC, sys.PC) for i := range sys.Regs { reg := sys.Regs[i] fmt.Fprintf(b, "r%-2d = %02X (%d)\n", i, reg, reg) } fmt.Fprintln(b) fmt.Fprintln(b, "--- [ memory ] ---") fmt.Fprintln(b) fmt.Fprintln(b, hex.Dump(sys.Mem[:])) fmt.Fprintln(b) fmt.Fprintln(b, "--- [ assembly ] ---") fmt.Fprintln(b) var prevNop, dots bool for i := 0; i < len(sys.Mem); i += op.InstSize { buf := binary.BigEndian.Uint16(sys.Mem[i:]) inst, err := op.Decode(buf) if err != nil { fmt.Fprintf(b, "0x%02X: <invalid assembly> 0x%04X\n", i, buf) prevNop = false dots = false continue } _, ok := inst.(*op.Nop) if ok { if prevNop { if !dots { fmt.Fprintf(b, "0x%02X: %s\n", i, "...") dots = true } } else { fmt.Fprintf(b, "0x%02X: %s\n", i, inst) prevNop = true } } else { fmt.Fprintf(b, "0x%02X: %s\n", i, inst) prevNop = false dots = false } } return string(b.Bytes()) }
// DecodeSlice decodes and returns the instructions of the byte slice. func DecodeSlice(p []byte) (insts []interface{}, err error) { if len(p)%op.InstSize != 0 { return nil, fmt.Errorf("asm.DecodeSlice: p len (%d) not evenly dividable by %d", len(p), op.InstSize) } insts = make([]interface{}, 0, len(p)/op.InstSize) for i := 0; i < len(p); i += op.InstSize { buf := binary.BigEndian.Uint16(p[i:]) inst, err := op.Decode(buf) if err != nil { return nil, err } insts = append(insts, inst) } return insts, nil }
// Decode decodes and returns the instructions read from r. func Decode(r io.Reader) (insts []interface{}, err error) { var buf uint16 for { err = binary.Read(r, binary.BigEndian, &buf) if err != nil { if err == io.EOF { break } return nil, fmt.Errorf("asm.Decode: read failure; %s", err) } inst, err := op.Decode(buf) if err != nil { return nil, err } insts = append(insts, inst) } return insts, nil }
// parseHex parses the provided hexadecimal string into a slice of instructions. func parseHex(s string) (insts []interface{}, err error) { if len(s)%4 != 0 { return nil, fmt.Errorf("parseHex: string len (%d) not evenly dividable by 4", len(s)) } insts = make([]interface{}, 0, len(s)/4) for i := 0; i < len(s); i += 4 { buf, err := strconv.ParseUint(s[i:i+4], 16, 16) if err != nil { return nil, err } inst, err := op.Decode(uint16(buf)) if err != nil { return nil, err } insts = append(insts, inst) } return insts, nil }