Skip to content

macro-expander: Problem when comparing 32 bit constant with W register #685

@AndreasKrall

Description

@AndreasKrall

The following 32 bit code for instruction SVEWHILEBWGE from sys/arch/sve behaves wrong (expanded macros):

  register        S : Index -> BitsX  // general purpose register file with stack pointer
  [overwrite source: zero]            // S is overwritten on write by zero extending the written value
  alias register  R = S(*)(31..0)     // lower half of general purpose register file with stack pointer
  [zero : X(31)]                      // X(31) is the zero register
  alias register  X = S               // general purpose register file with zero register
  [zero : W(31)]                      // X(31) is the zero register
  [overwrite source: zero]            // X is overwritten on write by zero extending the written value
  alias register W  = X(*)(31..0)     // lower half of general purpose register file with zero register


  constant MinSIntW : SIntW = 0x8000'0000

  instruction SVEWHILEBWGE : SVEWhileFormat =
    let left  = W(rn) in
    let right = W(rm) in
      let pred =
        if right = MinSIntW then
          PTrueB
        else
          ...
        }

The path for right = MinSIntW is not taken, whereas the code for the 64 bit variant works fine:

  constant MinSIntX : SIntX = 0x8000'0000'0000'0000

  instruction SVEWHILEBXGE : SVEWhileFormat =
    let left  = X(rn) in
    let right = X(rm) in
      let pred =
        if right = MinSIntX then
          PTrueB
        else
          ...

I assume that there are some typing and sign extension issues. Interestingly in the typed AST left and right are 64 bit, but right is later casted to SIntW in the comparison. But in the behavior graph it looks fine again.

The problem has been shown up in the following test code:

    mov     x3,  #0
    addvl   x3,  x3,  #1
    mov     w8,  #1
    ror     w8,  w8,  #1
    add     w9,  w8,  #1
    whilege p0.b,w8,  w8
    whilege p1.b,w9,  w8
    whilehs p2.b,w8,  w8
    whilehs p3.b,w9,  w8
    cntp    x13, p0, p0.b
    cntp    x14, p1, p1.b
    cntp    x15, p2, p2.b
    cntp    x16, p3, p3.b
    cmp     x13, x3
    b.ne    exit
    add     x2,  x2, #1
    cmp     x14, x3
    b.ne    exit
    add     x2,  x2, #1
    cmp     x15, x5
    b.ne    exit
    add     x2,  x2, #1
    cmp     x16, x6
    b.ne    exit
    add     x2,  x2, #1         // x2 = 0xA0

This test works fine:

    mov     x8,  #1
    ror     x8,  x8,  #1
    add     x9,  x8,  #1
    whilege p0.b,x8,  x8
    whilege p1.b,x9,  x8
    whilehs p2.b,x8,  x8
    whilehs p3.b,x9,  x8

And of course upstream QEMU produces the right result.

Metadata

Metadata

Labels

bugSomething isn't workingfrontendThis is frontend related

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions