github.com/jflude/taocp@v0.0.0-20240210234939-99f2a91af3c2/mix/cycle.go (about)

     1  package mix
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"strings"
     7  )
     8  
     9  var (
    10  	ErrInvalidAddress    = errors.New("mix: invalid address")
    11  	ErrInvalidIndex      = errors.New("mix: invalid index")
    12  	ErrInvalidOp         = errors.New("mix: invalid operation")
    13  	ErrContentsInterlock = errors.New("mix: contents interlock")
    14  )
    15  
    16  func (c *Computer) Cycle() (err error) {
    17  	defer func() {
    18  		if r := recover(); r != nil {
    19  			if err2, ok := r.(error); ok {
    20  				err = err2
    21  			} else {
    22  				panic(r)
    23  			}
    24  		}
    25  		if err != nil {
    26  			asm := "?"
    27  			if c.validAddress(c.next) {
    28  				asm = Disassemble(c.Contents[mBase+c.next])
    29  			}
    30  			err = fmt.Errorf("%w at %04d: %s",
    31  				err, c.next, strings.TrimSpace(asm))
    32  		}
    33  	}()
    34  	c.checkAddress(c.next)
    35  	c.checkInterlock(c.next, c.next)
    36  	aa, i, f, op := c.Contents[mBase+c.next].UnpackOp()
    37  	if i > 6 {
    38  		return ErrInvalidOp
    39  	}
    40  	m := aa.Int()
    41  	if i > 0 {
    42  		m += c.Reg[i].Int()
    43  		if m < MinIndex || m > MaxIndex {
    44  			return ErrInvalidIndex
    45  		}
    46  	}
    47  	if c.Tracer != nil && c.next >= c.Trigger {
    48  		c.printTrace(m, c.next)
    49  	}
    50  	state := c.ctrl
    51  	duration, err := microcode[op](c, aa, i, f, op, m)
    52  	if err != nil {
    53  		return err
    54  	}
    55  	c.Elapsed += duration
    56  	c.next++
    57  	if c.Interrupts {
    58  		c.checkInterrupt(state)
    59  	}
    60  	return nil
    61  }
    62  
    63  func (c *Computer) nop(aa Word, i, f, op, m int) (int64, error) {
    64  	return 1, nil
    65  }