-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathcanEncodeNumber.go
More file actions
115 lines (94 loc) 路 2.43 KB
/
Copy pathcanEncodeNumber.go
File metadata and controls
115 lines (94 loc) 路 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package codegen
import (
"git.urbach.dev/cli/q/src/arm"
"git.urbach.dev/cli/q/src/config"
"git.urbach.dev/cli/q/src/cpu"
"git.urbach.dev/cli/q/src/ssa"
"git.urbach.dev/cli/q/src/token"
)
// canEncodeNumber returns true if the architecture can encode an immediate for the given instruction.
func (f *Function) canEncodeNumber(instr ssa.Value, number *ssa.Int) bool {
switch instr := instr.(type) {
case *ssa.BinaryOp:
if number != instr.Right {
return false
}
switch f.build.Arch {
case config.ARM:
if instr.Op.IsComparison() {
_, encodable := arm.CompareRegisterNumber(0, number.Int)
return encodable
}
switch instr.Op {
case token.Add:
_, encodable := arm.AddRegisterNumber(0, 0, number.Int)
return encodable
case token.And:
_, encodable := arm.AndRegisterNumber(0, 0, number.Int)
return encodable
case token.Or:
_, encodable := arm.OrRegisterNumber(0, 0, number.Int)
return encodable
case token.Shl, token.Shr:
return number.Int >= 0 && number.Int <= 63
case token.Sub:
_, encodable := arm.SubRegisterNumber(0, 0, number.Int)
return encodable
case token.Xor:
_, encodable := arm.XorRegisterNumber(0, 0, number.Int)
return encodable
}
case config.X86:
if instr.Op.IsComparison() {
return cpu.SizeInt(number.Int) <= 4
}
switch instr.Op {
case token.Add, token.And, token.Or, token.Sub, token.Xor:
return cpu.SizeInt(number.Int) <= 4
case token.Shl, token.Shr:
return number.Int >= 0 && number.Int <= 63
}
}
case *ssa.Load:
if instr.Memory.Index != number {
return false
}
switch f.build.Arch {
case config.ARM:
if instr.Memory.Scale {
return number.Int >= 0 && number.Int <= 4095
} else {
return number.Int >= -256 && number.Int <= 255
}
case config.X86:
if instr.Memory.Scale {
return false
}
return number.Int >= -128 && number.Int <= 127
}
case *ssa.Store:
switch f.build.Arch {
case config.ARM:
if instr.Memory.Index == number {
if instr.Memory.Scale {
return number.Int >= 0 && number.Int <= 4095
} else {
return number.Int >= -256 && number.Int <= 255
}
}
return false
case config.X86:
if instr.Memory.Scale {
return false
}
if instr.Value == number && cpu.SizeInt(number.Int) <= 4 {
return true
}
if instr.Memory.Index == number && cpu.SizeInt(number.Int) <= 1 {
return true
}
return false
}
}
return false
}