Beispiel #1
0
// 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
}
Beispiel #2
0
// 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)
}
Beispiel #3
0
// 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())
}
Beispiel #4
0
// 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
}
Beispiel #5
0
// 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
}
Beispiel #6
0
// 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
}