Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 1 | // Copyright 2009 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Russ Cox | 17eba6e | 2015-05-21 13:28:10 -0400 | [diff] [blame] | 5 | package x86 |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 6 | |
| 7 | import ( |
Russ Cox | 17eba6e | 2015-05-21 13:28:10 -0400 | [diff] [blame] | 8 | "cmd/compile/internal/gc" |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 9 | "cmd/internal/obj" |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 10 | "cmd/internal/obj/x86" |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 11 | ) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 12 | |
| 13 | /* |
| 14 | * attempt to generate 64-bit |
| 15 | * res = n |
| 16 | * return 1 on success, 0 if op not handled. |
| 17 | */ |
| 18 | func cgen64(n *gc.Node, res *gc.Node) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 19 | if res.Op != gc.OINDREG && res.Op != gc.ONAME { |
| 20 | gc.Dump("n", n) |
| 21 | gc.Dump("res", res) |
Matthew Dempsky | c3dfad5 | 2016-03-07 08:23:55 -0800 | [diff] [blame^] | 22 | gc.Fatalf("cgen64 %v of %v", gc.Oconv(n.Op, 0), gc.Oconv(res.Op, 0)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 23 | } |
| 24 | |
| 25 | switch n.Op { |
| 26 | default: |
Matthew Dempsky | c3dfad5 | 2016-03-07 08:23:55 -0800 | [diff] [blame^] | 27 | gc.Fatalf("cgen64 %v", gc.Oconv(n.Op, 0)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 28 | |
| 29 | case gc.OMINUS: |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 30 | gc.Cgen(n.Left, res) |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 31 | var hi1 gc.Node |
| 32 | var lo1 gc.Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 33 | split64(res, &lo1, &hi1) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 34 | gins(x86.ANEGL, nil, &lo1) |
| 35 | gins(x86.AADCL, ncon(0), &hi1) |
| 36 | gins(x86.ANEGL, nil, &hi1) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 37 | splitclean() |
| 38 | return |
| 39 | |
| 40 | case gc.OCOM: |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 41 | gc.Cgen(n.Left, res) |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 42 | var lo1 gc.Node |
| 43 | var hi1 gc.Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 44 | split64(res, &lo1, &hi1) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 45 | gins(x86.ANOTL, nil, &lo1) |
| 46 | gins(x86.ANOTL, nil, &hi1) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 47 | splitclean() |
| 48 | return |
| 49 | |
| 50 | // binary operators. |
| 51 | // common setup below. |
| 52 | case gc.OADD, |
| 53 | gc.OSUB, |
| 54 | gc.OMUL, |
| 55 | gc.OLROT, |
| 56 | gc.OLSH, |
| 57 | gc.ORSH, |
| 58 | gc.OAND, |
| 59 | gc.OOR, |
| 60 | gc.OXOR: |
| 61 | break |
| 62 | } |
| 63 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 64 | l := n.Left |
| 65 | r := n.Right |
Josh Bleecher Snyder | 75883ba | 2015-04-02 19:58:37 -0700 | [diff] [blame] | 66 | if !l.Addable { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 67 | var t1 gc.Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 68 | gc.Tempname(&t1, l.Type) |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 69 | gc.Cgen(l, &t1) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 70 | l = &t1 |
| 71 | } |
| 72 | |
Josh Bleecher Snyder | 75883ba | 2015-04-02 19:58:37 -0700 | [diff] [blame] | 73 | if r != nil && !r.Addable { |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 74 | var t2 gc.Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 75 | gc.Tempname(&t2, r.Type) |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 76 | gc.Cgen(r, &t2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 77 | r = &t2 |
| 78 | } |
| 79 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 80 | var ax gc.Node |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 81 | gc.Nodreg(&ax, gc.Types[gc.TINT32], x86.REG_AX) |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 82 | var cx gc.Node |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 83 | gc.Nodreg(&cx, gc.Types[gc.TINT32], x86.REG_CX) |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 84 | var dx gc.Node |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 85 | gc.Nodreg(&dx, gc.Types[gc.TINT32], x86.REG_DX) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 86 | |
| 87 | // Setup for binary operation. |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 88 | var hi1 gc.Node |
| 89 | var lo1 gc.Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 90 | split64(l, &lo1, &hi1) |
| 91 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 92 | var lo2 gc.Node |
| 93 | var hi2 gc.Node |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 94 | if gc.Is64(r.Type) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 95 | split64(r, &lo2, &hi2) |
| 96 | } |
| 97 | |
Brad Fitzpatrick | 5fea2cc | 2016-03-01 23:21:55 +0000 | [diff] [blame] | 98 | // Do op. Leave result in DX:AX. |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 99 | switch n.Op { |
| 100 | // TODO: Constants |
| 101 | case gc.OADD: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 102 | gins(x86.AMOVL, &lo1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 103 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 104 | gins(x86.AMOVL, &hi1, &dx) |
| 105 | gins(x86.AADDL, &lo2, &ax) |
| 106 | gins(x86.AADCL, &hi2, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 107 | |
| 108 | // TODO: Constants. |
| 109 | case gc.OSUB: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 110 | gins(x86.AMOVL, &lo1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 111 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 112 | gins(x86.AMOVL, &hi1, &dx) |
| 113 | gins(x86.ASUBL, &lo2, &ax) |
| 114 | gins(x86.ASBBL, &hi2, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 115 | |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 116 | case gc.OMUL: |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 117 | // let's call the next three EX, FX and GX |
| 118 | var ex, fx, gx gc.Node |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 119 | gc.Regalloc(&ex, gc.Types[gc.TPTR32], nil) |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 120 | gc.Regalloc(&fx, gc.Types[gc.TPTR32], nil) |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 121 | gc.Regalloc(&gx, gc.Types[gc.TPTR32], nil) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 122 | |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 123 | // load args into DX:AX and EX:GX. |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 124 | gins(x86.AMOVL, &lo1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 125 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 126 | gins(x86.AMOVL, &hi1, &dx) |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 127 | gins(x86.AMOVL, &lo2, &gx) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 128 | gins(x86.AMOVL, &hi2, &ex) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 129 | |
| 130 | // if DX and EX are zero, use 32 x 32 -> 64 unsigned multiply. |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 131 | gins(x86.AMOVL, &dx, &fx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 132 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 133 | gins(x86.AORL, &ex, &fx) |
| 134 | p1 := gc.Gbranch(x86.AJNE, nil, 0) |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 135 | gins(x86.AMULL, &gx, nil) // implicit &ax |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 136 | p2 := gc.Gbranch(obj.AJMP, nil, 0) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 137 | gc.Patch(p1, gc.Pc) |
| 138 | |
| 139 | // full 64x64 -> 64, from 32x32 -> 64. |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 140 | gins(x86.AIMULL, &gx, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 141 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 142 | gins(x86.AMOVL, &ax, &fx) |
| 143 | gins(x86.AIMULL, &ex, &fx) |
| 144 | gins(x86.AADDL, &dx, &fx) |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 145 | gins(x86.AMOVL, &gx, &dx) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 146 | gins(x86.AMULL, &dx, nil) // implicit &ax |
| 147 | gins(x86.AADDL, &fx, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 148 | gc.Patch(p2, gc.Pc) |
| 149 | |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 150 | gc.Regfree(&ex) |
| 151 | gc.Regfree(&fx) |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 152 | gc.Regfree(&gx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 153 | |
Michael Hudson-Doyle | 9514285 | 2015-10-28 10:40:46 +1300 | [diff] [blame] | 154 | // We only rotate by a constant c in [0,64). |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 155 | // if c >= 32: |
| 156 | // lo, hi = hi, lo |
| 157 | // c -= 32 |
| 158 | // if c == 0: |
| 159 | // no-op |
| 160 | // else: |
| 161 | // t = hi |
| 162 | // shld hi:lo, c |
| 163 | // shld lo:t, c |
| 164 | case gc.OLROT: |
Josh Bleecher Snyder | 0112f6f | 2015-04-22 20:08:03 -0700 | [diff] [blame] | 165 | v := uint64(r.Int()) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 166 | |
| 167 | if v >= 32 { |
| 168 | // reverse during load to do the first 32 bits of rotate |
| 169 | v -= 32 |
| 170 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 171 | gins(x86.AMOVL, &lo1, &dx) |
| 172 | gins(x86.AMOVL, &hi1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 173 | } else { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 174 | gins(x86.AMOVL, &lo1, &ax) |
| 175 | gins(x86.AMOVL, &hi1, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 176 | } |
| 177 | |
| 178 | if v == 0 { |
| 179 | } else // done |
| 180 | { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 181 | gins(x86.AMOVL, &dx, &cx) |
| 182 | p1 := gins(x86.ASHLL, ncon(uint32(v)), &dx) |
| 183 | p1.From.Index = x86.REG_AX // double-width shift |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 184 | p1.From.Scale = 0 |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 185 | p1 = gins(x86.ASHLL, ncon(uint32(v)), &ax) |
| 186 | p1.From.Index = x86.REG_CX // double-width shift |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 187 | p1.From.Scale = 0 |
| 188 | } |
| 189 | |
| 190 | case gc.OLSH: |
| 191 | if r.Op == gc.OLITERAL { |
Josh Bleecher Snyder | 0112f6f | 2015-04-22 20:08:03 -0700 | [diff] [blame] | 192 | v := uint64(r.Int()) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 193 | if v >= 64 { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 194 | if gc.Is64(r.Type) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 195 | splitclean() |
| 196 | } |
| 197 | splitclean() |
| 198 | split64(res, &lo2, &hi2) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 199 | gins(x86.AMOVL, ncon(0), &lo2) |
| 200 | gins(x86.AMOVL, ncon(0), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 201 | splitclean() |
Russ Cox | 79f727a | 2015-03-02 12:35:15 -0500 | [diff] [blame] | 202 | return |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 203 | } |
| 204 | |
| 205 | if v >= 32 { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 206 | if gc.Is64(r.Type) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 207 | splitclean() |
| 208 | } |
| 209 | split64(res, &lo2, &hi2) |
| 210 | gmove(&lo1, &hi2) |
| 211 | if v > 32 { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 212 | gins(x86.ASHLL, ncon(uint32(v-32)), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 213 | } |
| 214 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 215 | gins(x86.AMOVL, ncon(0), &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 216 | splitclean() |
| 217 | splitclean() |
Russ Cox | 79f727a | 2015-03-02 12:35:15 -0500 | [diff] [blame] | 218 | return |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 219 | } |
| 220 | |
| 221 | // general shift |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 222 | gins(x86.AMOVL, &lo1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 223 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 224 | gins(x86.AMOVL, &hi1, &dx) |
| 225 | p1 := gins(x86.ASHLL, ncon(uint32(v)), &dx) |
| 226 | p1.From.Index = x86.REG_AX // double-width shift |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 227 | p1.From.Scale = 0 |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 228 | gins(x86.ASHLL, ncon(uint32(v)), &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 229 | break |
| 230 | } |
| 231 | |
| 232 | // load value into DX:AX. |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 233 | gins(x86.AMOVL, &lo1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 234 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 235 | gins(x86.AMOVL, &hi1, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 236 | |
| 237 | // load shift value into register. |
| 238 | // if high bits are set, zero value. |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 239 | var p1 *obj.Prog |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 240 | |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 241 | if gc.Is64(r.Type) { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 242 | gins(x86.ACMPL, &hi2, ncon(0)) |
| 243 | p1 = gc.Gbranch(x86.AJNE, nil, +1) |
| 244 | gins(x86.AMOVL, &lo2, &cx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 245 | } else { |
| 246 | cx.Type = gc.Types[gc.TUINT32] |
| 247 | gmove(r, &cx) |
| 248 | } |
| 249 | |
| 250 | // if shift count is >=64, zero value |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 251 | gins(x86.ACMPL, &cx, ncon(64)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 252 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 253 | p2 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT32]), nil, +1) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 254 | if p1 != nil { |
| 255 | gc.Patch(p1, gc.Pc) |
| 256 | } |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 257 | gins(x86.AXORL, &dx, &dx) |
| 258 | gins(x86.AXORL, &ax, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 259 | gc.Patch(p2, gc.Pc) |
| 260 | |
| 261 | // if shift count is >= 32, zero low. |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 262 | gins(x86.ACMPL, &cx, ncon(32)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 263 | |
| 264 | p1 = gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT32]), nil, +1) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 265 | gins(x86.AMOVL, &ax, &dx) |
| 266 | gins(x86.ASHLL, &cx, &dx) // SHLL only uses bottom 5 bits of count |
| 267 | gins(x86.AXORL, &ax, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 268 | p2 = gc.Gbranch(obj.AJMP, nil, 0) |
| 269 | gc.Patch(p1, gc.Pc) |
| 270 | |
| 271 | // general shift |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 272 | p1 = gins(x86.ASHLL, &cx, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 273 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 274 | p1.From.Index = x86.REG_AX // double-width shift |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 275 | p1.From.Scale = 0 |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 276 | gins(x86.ASHLL, &cx, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 277 | gc.Patch(p2, gc.Pc) |
| 278 | |
| 279 | case gc.ORSH: |
| 280 | if r.Op == gc.OLITERAL { |
Josh Bleecher Snyder | 0112f6f | 2015-04-22 20:08:03 -0700 | [diff] [blame] | 281 | v := uint64(r.Int()) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 282 | if v >= 64 { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 283 | if gc.Is64(r.Type) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 284 | splitclean() |
| 285 | } |
| 286 | splitclean() |
| 287 | split64(res, &lo2, &hi2) |
| 288 | if hi1.Type.Etype == gc.TINT32 { |
| 289 | gmove(&hi1, &lo2) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 290 | gins(x86.ASARL, ncon(31), &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 291 | gmove(&hi1, &hi2) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 292 | gins(x86.ASARL, ncon(31), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 293 | } else { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 294 | gins(x86.AMOVL, ncon(0), &lo2) |
| 295 | gins(x86.AMOVL, ncon(0), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 296 | } |
| 297 | |
| 298 | splitclean() |
Russ Cox | 79f727a | 2015-03-02 12:35:15 -0500 | [diff] [blame] | 299 | return |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 300 | } |
| 301 | |
| 302 | if v >= 32 { |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 303 | if gc.Is64(r.Type) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 304 | splitclean() |
| 305 | } |
| 306 | split64(res, &lo2, &hi2) |
| 307 | gmove(&hi1, &lo2) |
| 308 | if v > 32 { |
| 309 | gins(optoas(gc.ORSH, hi1.Type), ncon(uint32(v-32)), &lo2) |
| 310 | } |
| 311 | if hi1.Type.Etype == gc.TINT32 { |
| 312 | gmove(&hi1, &hi2) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 313 | gins(x86.ASARL, ncon(31), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 314 | } else { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 315 | gins(x86.AMOVL, ncon(0), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 316 | } |
| 317 | splitclean() |
| 318 | splitclean() |
Russ Cox | 79f727a | 2015-03-02 12:35:15 -0500 | [diff] [blame] | 319 | return |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | // general shift |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 323 | gins(x86.AMOVL, &lo1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 324 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 325 | gins(x86.AMOVL, &hi1, &dx) |
| 326 | p1 := gins(x86.ASHRL, ncon(uint32(v)), &ax) |
| 327 | p1.From.Index = x86.REG_DX // double-width shift |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 328 | p1.From.Scale = 0 |
| 329 | gins(optoas(gc.ORSH, hi1.Type), ncon(uint32(v)), &dx) |
| 330 | break |
| 331 | } |
| 332 | |
| 333 | // load value into DX:AX. |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 334 | gins(x86.AMOVL, &lo1, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 335 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 336 | gins(x86.AMOVL, &hi1, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 337 | |
| 338 | // load shift value into register. |
| 339 | // if high bits are set, zero value. |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 340 | var p1 *obj.Prog |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 341 | |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 342 | if gc.Is64(r.Type) { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 343 | gins(x86.ACMPL, &hi2, ncon(0)) |
| 344 | p1 = gc.Gbranch(x86.AJNE, nil, +1) |
| 345 | gins(x86.AMOVL, &lo2, &cx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 346 | } else { |
| 347 | cx.Type = gc.Types[gc.TUINT32] |
| 348 | gmove(r, &cx) |
| 349 | } |
| 350 | |
| 351 | // if shift count is >=64, zero or sign-extend value |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 352 | gins(x86.ACMPL, &cx, ncon(64)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 353 | |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 354 | p2 := gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT32]), nil, +1) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 355 | if p1 != nil { |
| 356 | gc.Patch(p1, gc.Pc) |
| 357 | } |
| 358 | if hi1.Type.Etype == gc.TINT32 { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 359 | gins(x86.ASARL, ncon(31), &dx) |
| 360 | gins(x86.AMOVL, &dx, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 361 | } else { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 362 | gins(x86.AXORL, &dx, &dx) |
| 363 | gins(x86.AXORL, &ax, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 364 | } |
| 365 | |
| 366 | gc.Patch(p2, gc.Pc) |
| 367 | |
| 368 | // if shift count is >= 32, sign-extend hi. |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 369 | gins(x86.ACMPL, &cx, ncon(32)) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 370 | |
| 371 | p1 = gc.Gbranch(optoas(gc.OLT, gc.Types[gc.TUINT32]), nil, +1) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 372 | gins(x86.AMOVL, &dx, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 373 | if hi1.Type.Etype == gc.TINT32 { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 374 | gins(x86.ASARL, &cx, &ax) // SARL only uses bottom 5 bits of count |
| 375 | gins(x86.ASARL, ncon(31), &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 376 | } else { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 377 | gins(x86.ASHRL, &cx, &ax) |
| 378 | gins(x86.AXORL, &dx, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 379 | } |
| 380 | |
| 381 | p2 = gc.Gbranch(obj.AJMP, nil, 0) |
| 382 | gc.Patch(p1, gc.Pc) |
| 383 | |
| 384 | // general shift |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 385 | p1 = gins(x86.ASHRL, &cx, &ax) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 386 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 387 | p1.From.Index = x86.REG_DX // double-width shift |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 388 | p1.From.Scale = 0 |
| 389 | gins(optoas(gc.ORSH, hi1.Type), &cx, &dx) |
| 390 | gc.Patch(p2, gc.Pc) |
| 391 | |
| 392 | // make constant the right side (it usually is anyway). |
| 393 | case gc.OXOR, |
| 394 | gc.OAND, |
| 395 | gc.OOR: |
| 396 | if lo1.Op == gc.OLITERAL { |
| 397 | nswap(&lo1, &lo2) |
| 398 | nswap(&hi1, &hi2) |
| 399 | } |
| 400 | |
| 401 | if lo2.Op == gc.OLITERAL { |
| 402 | // special cases for constants. |
Josh Bleecher Snyder | 0112f6f | 2015-04-22 20:08:03 -0700 | [diff] [blame] | 403 | lv := uint32(lo2.Int()) |
| 404 | hv := uint32(hi2.Int()) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 405 | splitclean() // right side |
| 406 | split64(res, &lo2, &hi2) |
| 407 | switch n.Op { |
| 408 | case gc.OXOR: |
| 409 | gmove(&lo1, &lo2) |
| 410 | gmove(&hi1, &hi2) |
| 411 | switch lv { |
| 412 | case 0: |
| 413 | break |
| 414 | |
| 415 | case 0xffffffff: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 416 | gins(x86.ANOTL, nil, &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 417 | |
| 418 | default: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 419 | gins(x86.AXORL, ncon(lv), &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 420 | } |
| 421 | |
| 422 | switch hv { |
| 423 | case 0: |
| 424 | break |
| 425 | |
| 426 | case 0xffffffff: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 427 | gins(x86.ANOTL, nil, &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 428 | |
| 429 | default: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 430 | gins(x86.AXORL, ncon(hv), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 431 | } |
| 432 | |
| 433 | case gc.OAND: |
| 434 | switch lv { |
| 435 | case 0: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 436 | gins(x86.AMOVL, ncon(0), &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 437 | |
| 438 | default: |
| 439 | gmove(&lo1, &lo2) |
| 440 | if lv != 0xffffffff { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 441 | gins(x86.AANDL, ncon(lv), &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 442 | } |
| 443 | } |
| 444 | |
| 445 | switch hv { |
| 446 | case 0: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 447 | gins(x86.AMOVL, ncon(0), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 448 | |
| 449 | default: |
| 450 | gmove(&hi1, &hi2) |
| 451 | if hv != 0xffffffff { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 452 | gins(x86.AANDL, ncon(hv), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 453 | } |
| 454 | } |
| 455 | |
| 456 | case gc.OOR: |
| 457 | switch lv { |
| 458 | case 0: |
| 459 | gmove(&lo1, &lo2) |
| 460 | |
| 461 | case 0xffffffff: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 462 | gins(x86.AMOVL, ncon(0xffffffff), &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 463 | |
| 464 | default: |
| 465 | gmove(&lo1, &lo2) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 466 | gins(x86.AORL, ncon(lv), &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 467 | } |
| 468 | |
| 469 | switch hv { |
| 470 | case 0: |
| 471 | gmove(&hi1, &hi2) |
| 472 | |
| 473 | case 0xffffffff: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 474 | gins(x86.AMOVL, ncon(0xffffffff), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 475 | |
| 476 | default: |
| 477 | gmove(&hi1, &hi2) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 478 | gins(x86.AORL, ncon(hv), &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 479 | } |
| 480 | } |
| 481 | |
| 482 | splitclean() |
| 483 | splitclean() |
Russ Cox | 79f727a | 2015-03-02 12:35:15 -0500 | [diff] [blame] | 484 | return |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 485 | } |
| 486 | |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 487 | gins(x86.AMOVL, &lo1, &ax) |
| 488 | gins(x86.AMOVL, &hi1, &dx) |
Marvin Stenger | 8e7a3ea | 2015-09-24 23:21:18 +0200 | [diff] [blame] | 489 | gins(optoas(n.Op, lo1.Type), &lo2, &ax) |
| 490 | gins(optoas(n.Op, lo1.Type), &hi2, &dx) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 491 | } |
| 492 | |
Russ Cox | dc7b54b | 2015-02-17 22:13:49 -0500 | [diff] [blame] | 493 | if gc.Is64(r.Type) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 494 | splitclean() |
| 495 | } |
| 496 | splitclean() |
| 497 | |
| 498 | split64(res, &lo1, &hi1) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 499 | gins(x86.AMOVL, &ax, &lo1) |
| 500 | gins(x86.AMOVL, &dx, &hi1) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 501 | splitclean() |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 502 | } |
| 503 | |
| 504 | /* |
| 505 | * generate comparison of nl, nr, both 64-bit. |
| 506 | * nl is memory; nr is constant or memory. |
| 507 | */ |
Marvin Stenger | 8e7a3ea | 2015-09-24 23:21:18 +0200 | [diff] [blame] | 508 | func cmp64(nl *gc.Node, nr *gc.Node, op gc.Op, likely int, to *obj.Prog) { |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 509 | var lo1 gc.Node |
| 510 | var hi1 gc.Node |
| 511 | var lo2 gc.Node |
| 512 | var hi2 gc.Node |
| 513 | var rr gc.Node |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 514 | |
| 515 | split64(nl, &lo1, &hi1) |
| 516 | split64(nr, &lo2, &hi2) |
| 517 | |
| 518 | // compare most significant word; |
| 519 | // if they differ, we're done. |
Russ Cox | 382b44e | 2015-02-23 16:07:24 -0500 | [diff] [blame] | 520 | t := hi1.Type |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 521 | |
| 522 | if nl.Op == gc.OLITERAL || nr.Op == gc.OLITERAL { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 523 | gins(x86.ACMPL, &hi1, &hi2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 524 | } else { |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 525 | gc.Regalloc(&rr, gc.Types[gc.TINT32], nil) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 526 | gins(x86.AMOVL, &hi1, &rr) |
| 527 | gins(x86.ACMPL, &rr, &hi2) |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 528 | gc.Regfree(&rr) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 529 | } |
| 530 | |
Russ Cox | 175929b | 2015-03-02 14:22:05 -0500 | [diff] [blame] | 531 | var br *obj.Prog |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 532 | switch op { |
| 533 | default: |
Matthew Dempsky | c3dfad5 | 2016-03-07 08:23:55 -0800 | [diff] [blame^] | 534 | gc.Fatalf("cmp64 %v %v", gc.Oconv(op, 0), t) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 535 | |
| 536 | // cmp hi |
| 537 | // jne L |
| 538 | // cmp lo |
| 539 | // jeq to |
| 540 | // L: |
| 541 | case gc.OEQ: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 542 | br = gc.Gbranch(x86.AJNE, nil, -likely) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 543 | |
| 544 | // cmp hi |
| 545 | // jne to |
| 546 | // cmp lo |
| 547 | // jne to |
| 548 | case gc.ONE: |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 549 | gc.Patch(gc.Gbranch(x86.AJNE, nil, likely), to) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 550 | |
| 551 | // cmp hi |
| 552 | // jgt to |
| 553 | // jlt L |
| 554 | // cmp lo |
| 555 | // jge to (or jgt to) |
| 556 | // L: |
| 557 | case gc.OGE, |
| 558 | gc.OGT: |
| 559 | gc.Patch(gc.Gbranch(optoas(gc.OGT, t), nil, likely), to) |
| 560 | |
| 561 | br = gc.Gbranch(optoas(gc.OLT, t), nil, -likely) |
| 562 | |
| 563 | // cmp hi |
| 564 | // jlt to |
| 565 | // jgt L |
| 566 | // cmp lo |
| 567 | // jle to (or jlt to) |
| 568 | // L: |
| 569 | case gc.OLE, |
| 570 | gc.OLT: |
| 571 | gc.Patch(gc.Gbranch(optoas(gc.OLT, t), nil, likely), to) |
| 572 | |
| 573 | br = gc.Gbranch(optoas(gc.OGT, t), nil, -likely) |
| 574 | } |
| 575 | |
| 576 | // compare least significant word |
| 577 | t = lo1.Type |
| 578 | |
| 579 | if nl.Op == gc.OLITERAL || nr.Op == gc.OLITERAL { |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 580 | gins(x86.ACMPL, &lo1, &lo2) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 581 | } else { |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 582 | gc.Regalloc(&rr, gc.Types[gc.TINT32], nil) |
Russ Cox | 8afb396 | 2015-03-04 22:58:27 -0500 | [diff] [blame] | 583 | gins(x86.AMOVL, &lo1, &rr) |
| 584 | gins(x86.ACMPL, &rr, &lo2) |
Russ Cox | b115c35 | 2015-03-18 17:26:36 -0400 | [diff] [blame] | 585 | gc.Regfree(&rr) |
Russ Cox | 8c195bd | 2015-02-13 14:40:36 -0500 | [diff] [blame] | 586 | } |
| 587 | |
| 588 | // jump again |
| 589 | gc.Patch(gc.Gbranch(optoas(op, t), nil, likely), to) |
| 590 | |
| 591 | // point first branch down here if appropriate |
| 592 | if br != nil { |
| 593 | gc.Patch(br, gc.Pc) |
| 594 | } |
| 595 | |
| 596 | splitclean() |
| 597 | splitclean() |
| 598 | } |