github.com/jflude/taocp@v0.0.0-20240210234939-99f2a91af3c2/mix/field.go (about) 1 package mix 2 3 import "errors" 4 5 var ErrInvalidSpec = errors.New("mix: invalid field specification") 6 7 // Spec returns the integer equivalent of a MIX field specification. 8 func Spec(left, right int) int { 9 return 8*left + right 10 } 11 12 func checkSpec(f int) { 13 if f >= len(fields) || fields[f].shift == -1 { 14 panic(ErrInvalidSpec) 15 } 16 } 17 18 // Field returns the value of MIX word w's field f, as a MIX word. 19 func (w Word) Field(f int) Word { 20 if f == 5 { 21 return w 22 } 23 checkSpec(f) 24 return Word((int32(w) >> fields[f].shift) & fields[f].reg) 25 } 26 27 // SetField changes the field f of the MIX word w to the given value. 28 func (w *Word) SetField(f int, val Word) { 29 if f == 5 { 30 *w = val 31 return 32 } 33 checkSpec(f) 34 *w = Word((int32(*w) &^ fields[f].mem) | 35 ((int32(val) << fields[f].shift) & fields[f].mem) | 36 (int32(val) & fields[f].sign)) 37 } 38 39 // PackOp composes a MIX word from a MIX instruction's address, index, field 40 // and opcode. 41 func (w *Word) PackOp(aa Word, i, f, c int) { 42 *w = Word((int32(aa) & fields[02].sign) | 43 (int32(aa) << fields[02].shift & fields[02].mem) | 44 (int32(i) << fields[033].shift & fields[033].mem) | 45 (int32(f) << fields[044].shift & fields[044].mem) | 46 (int32(c) << fields[055].shift & fields[055].mem)) 47 } 48 49 // UnpackOp extracts a MIX instruction's address, index, field and opcode 50 // from a MIX word. 51 func (w Word) UnpackOp() (aa Word, i, f, c int) { 52 aa = Word((int32(w) >> fields[02].shift) & fields[02].reg) 53 i = int((int32(w) & fields[033].mem) >> fields[033].shift) 54 f = int((int32(w) & fields[044].mem) >> fields[044].shift) 55 c = int((int32(w) & fields[055].mem) >> fields[055].shift) 56 return 57 } 58 59 // PackFloat composes a MIX word from a floating point number's exponent 60 // and fraction. 61 func (w *Word) PackFloat(e, f int) { 62 *w = Word(0) // TODO 63 } 64 65 // UnpackFloat extracts the exponent and fraction of a floating point number 66 // in a MIX word. 67 func (w Word) UnpackFloat() (e, f int) { 68 e = int((int32(w) & fields[011].mem) >> fields[011].shift) // ?? 69 f = int(0) // TODO 70 return 71 } 72 73 var fields = [...]struct { 74 mem int32 // memory mask 75 reg int32 // register mask 76 sign int32 // sign affected 77 shift int // how much to shift to align receiver and source 78 }{ 79 {signBit, signBit, signBit, 0}, // [0:0] 80 {07700000000 | signBit, 00000000077 | signBit, signBit, 24}, // [0:1] 81 {07777000000 | signBit, 00000007777 | signBit, signBit, 18}, // [0:2] 82 {07777770000 | signBit, 00000777777 | signBit, signBit, 12}, // [0:3] 83 {07777777700 | signBit, 00077777777 | signBit, signBit, 6}, // [0:4] 84 {07777777777 | signBit, 07777777777 | signBit, signBit, 0}, // [0:5] 85 {0, 0, 0, -1}, 86 {0, 0, 0, -1}, 87 {0, 0, 0, -1}, 88 {07700000000, 000000000077, 0, 24}, // [1:1] 89 {07777000000, 000000007777, 0, 18}, // [1:2] 90 {07777770000, 000000777777, 0, 12}, // [1:3] 91 {07777777700, 000077777777, 0, 6}, // [1:4] 92 {07777777777, 007777777777, 0, 0}, // [1:5] 93 {0, 0, 0, -1}, 94 {0, 0, 0, -1}, 95 {0, 0, 0, -1}, 96 {0, 0, 0, -1}, 97 {00077000000, 000000000077, 0, 18}, // [2:2] 98 {00077770000, 000000007777, 0, 12}, // [2:3] 99 {00077777700, 000000777777, 0, 6}, // [2:4] 100 {00077777777, 000077777777, 0, 0}, // [2:5] 101 {0, 0, 0, -1}, 102 {0, 0, 0, -1}, 103 {0, 0, 0, -1}, 104 {0, 0, 0, -1}, 105 {0, 0, 0, -1}, 106 {00000770000, 000000000077, 0, 12}, // [3:3] 107 {00000777700, 000000007777, 0, 6}, // [3:4] 108 {00000777777, 000000777777, 0, 0}, // [3:5] 109 {0, 0, 0, -1}, 110 {0, 0, 0, -1}, 111 {0, 0, 0, -1}, 112 {0, 0, 0, -1}, 113 {0, 0, 0, -1}, 114 {0, 0, 0, -1}, 115 {00000007700, 000000000077, 0, 6}, // [4:4] 116 {00000007777, 000000007777, 0, 0}, // [4:5] 117 {0, 0, 0, -1}, 118 {0, 0, 0, -1}, 119 {0, 0, 0, -1}, 120 {0, 0, 0, -1}, 121 {0, 0, 0, -1}, 122 {0, 0, 0, -1}, 123 {0, 0, 0, -1}, 124 {00000000077, 000000000077, 0, 0}, // [5:5] 125 }