-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy patharm_lower_data.go
More file actions
108 lines (104 loc) · 3.08 KB
/
Copy patharm_lower_data.go
File metadata and controls
108 lines (104 loc) · 3.08 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
package plan9asm
import (
"fmt"
"strings"
)
func (c *armCtx) lowerData(op, cond string, postInc bool, ins Instr) (ok bool, terminated bool, err error) {
switch op {
case "MOVD":
if len(ins.Args) != 2 {
return true, false, fmt.Errorf("arm MOVD expects 2 operands: %q", ins.Raw)
}
src, dst := ins.Args[0], ins.Args[1]
switch {
case src.Kind == OpReg && strings.HasPrefix(string(src.Reg), "F") && dst.Kind == OpMem:
v, err := c.loadFReg(src.Reg)
if err != nil {
return true, false, err
}
return true, false, c.storeMem(dst.Mem, 64, postInc, v)
case src.Kind == OpMem && dst.Kind == OpReg && strings.HasPrefix(string(dst.Reg), "F"):
v, err := c.loadMem(src.Mem, 64, postInc, false)
if err != nil {
return true, false, err
}
return true, false, c.storeFReg(dst.Reg, v)
case src.Kind == OpReg && strings.HasPrefix(string(src.Reg), "F") && dst.Kind == OpReg && strings.HasPrefix(string(dst.Reg), "F"):
v, err := c.loadFReg(src.Reg)
if err != nil {
return true, false, err
}
return true, false, c.storeFReg(dst.Reg, v)
default:
return true, false, fmt.Errorf("arm MOVD unsupported operands: %q", ins.Raw)
}
case "MOVW":
if len(ins.Args) != 2 {
return true, false, fmt.Errorf("arm MOVW expects 2 operands: %q", ins.Raw)
}
src, dst := ins.Args[0], ins.Args[1]
v := ""
if src.Kind == OpMem {
v, err = c.loadMem(src.Mem, 32, postInc, false)
} else {
v, err = c.eval32(src, false)
}
if err != nil {
return true, false, err
}
return true, false, c.storeARMValue(dst, v, 32, cond, postInc, ins.Raw)
case "MOVB", "MOVBU":
if len(ins.Args) != 2 {
return true, false, fmt.Errorf("arm %s expects 2 operands: %q", op, ins.Raw)
}
src, dst := ins.Args[0], ins.Args[1]
v := ""
if src.Kind == OpMem {
v, err = c.loadMem(src.Mem, 8, postInc, op == "MOVB")
} else {
v, err = c.eval32(src, false)
}
if err != nil {
return true, false, err
}
return true, false, c.storeARMValue(dst, v, 8, cond, postInc, ins.Raw)
}
return false, false, nil
}
func (c *armCtx) selectRegWrite(dst Reg, cond string, newV string) error {
if cond == "" || strings.EqualFold(cond, "AL") {
return c.storeReg(dst, newV)
}
cv, err := c.condValue(cond)
if err != nil {
return err
}
oldV, err := c.loadReg(dst)
if err != nil {
return err
}
t := c.newTmp()
fmt.Fprintf(c.b, " %%%s = select i1 %s, i32 %s, i32 %s\n", t, cv, newV, oldV)
return c.storeReg(dst, "%"+t)
}
func (c *armCtx) storeARMValue(dst Operand, v string, bits int, cond string, postInc bool, raw string) error {
switch dst.Kind {
case OpReg:
// ARM register file holds full words; loads already extended to i32.
return c.selectRegWrite(dst.Reg, cond, v)
case OpMem:
if cond != "" {
return fmt.Errorf("arm conditional store to memory unsupported: %q", raw)
}
return c.storeMem(dst.Mem, bits, postInc, v)
case OpFP:
if cond != "" {
return fmt.Errorf("arm conditional store to FP slot unsupported: %q", raw)
}
return c.storeFPResult32(dst.FPOffset, v)
case OpSym:
return nil
default:
return fmt.Errorf("arm unsupported dst operand: %q", raw)
}
}