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 }