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

     1  package mix
     2  
     3  import "container/heap"
     4  
     5  const tickRate = 1000
     6  
     7  // see Ex. 18, Section 1.4.4
     8  func (c *Computer) checkInterrupt(currentState bool) {
     9  	if c.ctrl != currentState {
    10  		if c.ctrl {
    11  			c.saveRegs()
    12  			c.next = -12
    13  		} else {
    14  			c.loadRegs()
    15  		}
    16  		return
    17  	}
    18  	if since := c.Elapsed - c.lastTick; since >= tickRate {
    19  		c.checkInterlock(-10, -10)
    20  		prev := int64(c.Contents[mBase-10].Int())
    21  		now := prev - since/tickRate
    22  		if prev > 0 && now <= 0 {
    23  			c.schedule(c.lastTick+prev*tickRate, -11)
    24  		}
    25  		c.Contents[mBase-10] = NewWord(int(now))
    26  		c.lastTick = c.Elapsed - c.Elapsed%tickRate
    27  	}
    28  	if !c.ctrl && c.pending.Len() > 0 && c.pending[0].when <= c.Elapsed {
    29  		ev := heap.Pop(&c.pending).(event)
    30  		c.saveRegs()
    31  		c.ctrl = true
    32  		c.next = ev.loc
    33  	}
    34  }
    35  
    36  func (c *Computer) saveRegs() {
    37  	c.checkInterlock(-9, 0)
    38  	copy(c.Contents[mBase-9:], c.Reg[:J])
    39  	w := c.Reg[J]
    40  	w.SetField(Spec(0, 2), NewWord(c.next))
    41  	ov := 0
    42  	if c.Overflow {
    43  		ov = 1
    44  	}
    45  	w.SetField(Spec(3, 3), NewWord(Spec(ov, c.Comparison+1)))
    46  	c.Contents[mBase-1] = w
    47  }
    48  
    49  func (c *Computer) loadRegs() {
    50  	c.checkInterlock(-9, 0)
    51  	copy(c.Reg[:J], c.Contents[mBase-9:])
    52  	w := c.Contents[mBase-1]
    53  	c.Reg[J] = w.Field(Spec(4, 5))
    54  	c.next = w.Field(Spec(1, 2)).Int()
    55  	ovci := w.Field(Spec(3, 3)).Int()
    56  	c.Overflow = (ovci/8 == 1)
    57  	c.Comparison = ovci%8 - 1
    58  }
    59  
    60  func (c *Computer) schedule(when int64, loc int) {
    61  	heap.Push(&c.pending, event{when, loc})
    62  }