in x86/x86map/map.go [968:1116]
func emitScanFunc(p *Prog, out *[]uint16) uint16 {
keys := p.keys()
text := treeText(p)
if off, ok := scanCache[text]; ok {
return off
}
start := uint16(len(*out))
scanCache[text] = start
switch p.Action {
case "decode":
if keys[0][0] != '/' {
*out = append(*out, scanSwitchByte)
off := len(*out)
for i := 0; i < 256; i++ {
*out = append(*out, 0)
}
for _, key := range keys {
val, n := decodeKeyPlus(key)
dst := emitScanFunc(p.Child[key], out)
for j := 0; j < n; j++ {
(*out)[off+val+j] = dst
}
}
return start
}
n := len(keys)
for n > 0 && keys[n-1][0] != '/' {
n--
}
total := 0
for i := n; i < len(keys); i++ {
key := keys[i]
_, n := decodeKeyPlus(key)
total += n
}
*out = append(*out, scanSwitchSlash, uint16(total))
off := len(*out)
for i := 0; i < total; i++ {
*out = append(*out, 0, 0)
}
for i := 0; i < 8; i++ {
*out = append(*out, 0)
}
for i := n; i < len(keys); i++ {
key := keys[i]
val, valn := decodeKeyPlus(key)
targ := emitScanFunc(p.Child[key], out)
for j := 0; j < valn; j++ {
(*out)[off] = uint16(val + j)
off++
(*out)[off] = targ
off++
}
}
for i := 0; i < n; i++ {
key := keys[i]
if len(key) != 2 || key[0] != '/' || key[1] < '0' || '8' <= key[1] {
log.Fatalf("unexpected decode key %q", key)
}
(*out)[off+int(key[1]-'0')] = emitScanFunc(p.Child[key], out)
}
return start
case "read":
switch keys[0] {
default:
log.Fatalf("unexpected read %q", keys[0])
case "/r":
*out = append(*out, scanReadModRM)
case "ib":
*out = append(*out, scanReadIB)
case "iw":
*out = append(*out, scanReadIW)
case "cb":
*out = append(*out, scanReadCB)
case "cm":
*out = append(*out, scanReadCM)
case "iwd/d":
*out = append(*out, scanReadIWD)
case "iwdo/d":
*out = append(*out, scanReadIWDO)
case "cwd/d":
*out = append(*out, scanReadCWD)
case "cdp/d":
*out = append(*out, scanReadCDP)
}
next := p.Child[keys[0]]
if next.Action == "match" {
*out = append(*out, scanMatch)
} else {
*out = append(*out, scanJump, 0)
off := len(*out)
(*out)[off-1] = emitScanFunc(next, out)
}
return start
case "match":
*out = append(*out, scanMatch)
return start
case "is64":
*out = append(*out, scanSwitchIs64, 0, 0)
if next := p.Child["0"]; next != nil {
(*out)[start+1] = emitScanFunc(next, out)
}
if next := p.Child["1"]; next != nil {
(*out)[start+2] = emitScanFunc(next, out)
}
return start
case "ismem":
*out = append(*out, scanSwitchIsMem, 0, 0)
if next := p.Child["0"]; next != nil {
(*out)[start+1] = emitScanFunc(next, out)
}
if next := p.Child["1"]; next != nil {
(*out)[start+2] = emitScanFunc(next, out)
}
return start
case "datasize":
*out = append(*out, scanSwitchDatasize, 0, 0, 0)
if next := p.Child["16"]; next != nil {
(*out)[start+1] = emitScanFunc(next, out)
}
if next := p.Child["32"]; next != nil {
(*out)[start+2] = emitScanFunc(next, out)
}
if next := p.Child["64"]; next != nil {
(*out)[start+3] = emitScanFunc(next, out)
}
return start
case "prefix":
*out = append(*out, scanSwitchPrefix, uint16(len(keys)))
n := len(keys)
for i := 0; i < n; i++ {
*out = append(*out, uint16(decodeKey(keys[i])), 0)
}
for i := 0; i < n; i++ {
(*out)[int(start)+2+2*i+1] = emitScanFunc(p.Child[keys[i]], out)
}
return start
}
log.Fatalf("unexpected action %q", p.Action)
return start
}