Skip to content

Commit d99a3f0

Browse files
committed
cmd/asm: add support for LDREXB/STREXB
These are ARM Load/Store atomics that operate on bytes and are available starting from armv6k. See https://developer.arm.com/documentation/dui0379/e/arm-and-thumb-instructions/strex For six-nine-seven-three-five Change-Id: I2614ea46334df5c14d822238232cd19783145ddd
1 parent f2d118f commit d99a3f0

File tree

6 files changed

+33
-5
lines changed

6 files changed

+33
-5
lines changed

src/cmd/asm/internal/arch/arm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func IsARMCMP(op obj.As) bool {
101101
// one of the STREX-like instructions that require special handling.
102102
func IsARMSTREX(op obj.As) bool {
103103
switch op {
104-
case arm.ASTREX, arm.ASTREXD, arm.ASWPW, arm.ASWPBU:
104+
case arm.ASTREX, arm.ASTREXD, arm.ASTREXB, arm.ASWPW, arm.ASWPBU:
105105
return true
106106
}
107107
return false

src/cmd/asm/internal/asm/testdata/armerror.s

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,5 +260,9 @@ TEXT errors(SB),$0
260260
STREXD R0, (R2), R1 // ERROR "cannot use same register as both source and destination"
261261
STREXD R0, (R2), R2 // ERROR "cannot use same register as both source and destination"
262262
STREXD R1, (R4), R7 // ERROR "must be even"
263+
STREXB R0, (R2), R0 // ERROR "cannot use same register as both source and destination"
264+
STREXB R0, (R2), R1 // ERROR "cannot use same register as both source and destination"
265+
STREXB R0, (R2), R2 // ERROR "cannot use same register as both source and destination"
266+
STREXB R1, (R4), R7 // ERROR "must be even"
263267

264268
END

src/cmd/asm/internal/asm/testdata/armv6.s

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ TEXT foo(SB), DUPOK|NOSPLIT, $0
5252
MOVDF F4, F5 // c45bb7ee
5353

5454
LDREX (R8), R9 // 9f9f98e1
55+
LDREXB (R11), R12 // 9fcfdbe1
5556
LDREXD (R11), R12 // 9fcfbbe1
5657
STREX R3, (R4), R5 // STREX (R4), R3, R5 // 935f84e1
58+
STREXB R8, (R9), g // STREXB (R9), R8, g // 98afc9e1
5759
STREXD R8, (R9), g // STREXD (R9), R8, g // 98afa9e1
5860

5961
CMPF F8, F9 // c89ab4ee10faf1ee

src/cmd/internal/obj/arm/a.out.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,9 @@ const (
333333
ALDREX
334334
ASTREX
335335
ALDREXD
336+
ALDREXB
336337
ASTREXD
338+
ASTREXB
337339

338340
ADMB
339341

src/cmd/internal/obj/arm/anames.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/internal/obj/arm/asm5.go

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,9 @@ var optab = []Optab{
318318
{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0},
319319
{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0},
320320
{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0},
321+
{ALDREXB, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0},
321322
{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0},
323+
{ASTREXB, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0},
322324
{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0},
323325
{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0},
324326
{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0},
@@ -1432,7 +1434,9 @@ func buildop(ctxt *obj.Link) {
14321434
case ALDREX,
14331435
ASTREX,
14341436
ALDREXD,
1437+
ALDREXB,
14351438
ASTREXD,
1439+
ASTREXB,
14361440
ADMB,
14371441
APLD,
14381442
AAND,
@@ -2397,18 +2401,25 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
23972401
o1 |= (uint32(p.From.Reg) & 15) << 16
23982402
o1 |= (uint32(p.To.Reg) & 15) << 12
23992403

2400-
case 91: /* ldrexd oreg,reg */
2404+
case 91: /* ldrexd/ldrexb oreg,reg */
24012405
c.aclass(&p.From)
24022406

24032407
if c.instoffset != 0 {
24042408
c.ctxt.Diag("offset must be zero in LDREX")
24052409
}
2406-
o1 = 0x1b<<20 | 0xf9f
2410+
2411+
switch p.As {
2412+
case ALDREXD:
2413+
o1 = 0x1b << 20
2414+
case ALDREXB:
2415+
o1 = 0x1d << 20
2416+
}
2417+
o1 |= 0xf9f
24072418
o1 |= (uint32(p.From.Reg) & 15) << 16
24082419
o1 |= (uint32(p.To.Reg) & 15) << 12
24092420
o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
24102421

2411-
case 92: /* strexd reg,oreg,reg */
2422+
case 92: /* strexd/strexb reg,oreg,reg */
24122423
c.aclass(&p.From)
24132424

24142425
if c.instoffset != 0 {
@@ -2420,7 +2431,14 @@ func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
24202431
if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 {
24212432
c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
24222433
}
2423-
o1 = 0x1a<<20 | 0xf90
2434+
2435+
switch p.As {
2436+
case ASTREXD:
2437+
o1 = 0x1a << 20
2438+
case ASTREXB:
2439+
o1 = 0x1c << 20
2440+
}
2441+
o1 |= 0xf90
24242442
o1 |= (uint32(p.From.Reg) & 15) << 16
24252443
o1 |= (uint32(p.Reg) & 15) << 0
24262444
o1 |= (uint32(p.To.Reg) & 15) << 12

0 commit comments

Comments
 (0)