How do I write NOT Operation for the Risc-V (Assembly Language)?

前端 未结 1 1299
醉话见心
醉话见心 2021-01-24 00:31

How do I write NOT Operation for the Risc-V (Assembly Language)? If there\'s no NOT instruction, how do you achieve the same thing?

1条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-24 01:07

    Like MIPS and some other architectures, RISC V does not provide dedicated instructions for many things, including two-operand unary operations, as these operations can be had using their three-operand format, usually with x0 as the third operand, but sometimes constant 1 or -1 as the third operand.

    For convenience, the assembler will accept what are called pseudo instructions for these unary operations (and others).  Here's a list of the common RISC V pseudo instructions and their replacements.

    To do more complex or unlisted things, use math & logic, and as many instructions as needed.

    li rd, immediate     | Myriad sequences               | Load immediate
    mv rd, rs            | addi rd, rs, 0                 | Copy register
    not rd, rs           | xori rd, rs, -1                | One’s complement
    neg rd, rs           | sub rd, x0, rs                 | Two’s complement
    negw rd, rs          | subw rd, x0, rs                | Two’s complement word
    sext.w rd, rs        | addiw rd, rs, 0                | Sign extend word
    seqz rd, rs          | sltiu rd, rs, 1                | Set if = zero
    snez rd, rs          | sltu rd, x0, rs                | Set if ̸= zero
    sltz rd, rs          | slt rd, rs, x0                 | Set if < zero
    sgtz rd, rs          | slt rd, x0, rs                 | Set if > zero
    beqz rs, offset      | beq rs, x0, offset             | Branch if = zero
    bnez rs, offset      | bne rs, x0, offset             | Branch if ̸= zero
    blez rs, offset      | bge x0, rs, offset             | Branch if ≤ zero
    bgez rs, offset      | bge rs, x0, offset             | Branch if ≥ zero
    bltz rs, offset      | blt rs, x0, offset             | Branch if < zero
    bgtz rs, offset      | blt x0, rs, offset             | Branch if > zero
    bgt rs, rt, offset   | blt rt, rs, offset             | Branch if >
    ble rs, rt, offset   | bge rt, rs, offset             | Branch if ≤
    bgtu rs, rt, offset  | bltu rt, rs, offset            | Branch if >, unsigned
    bleu rs, rt, offset  | bgeu rt, rs, offset            | Branch if ≤, unsigned
    j offset             | jal x0, offset                 | Jump
    jal offset           | jal x1, offset                 | Jump and link
    jr rs                | jalr x0, 0(rs)                 | Jump register
    jalr rs              | jalr x1, 0(rs)                 | Jump and link register
    ret                  | jalr x0, 0(x1)                 | Return from subroutine
    call aa              | auipc x1, aa[31 : 12] + aa[11] | Call far-away subroutine
                         | jalr x1, aa[11:0](x1)          | (two instructions)
    tail aa              | auipc x6, aa[31 : 12] + aa[11] | Tail call far-away subroutine
                         | jalr x0, aa[11:0](x6)          | (also two instructions)
    

    As an aside, there's an educational processor called the LC-3.  It has only three arithmetic/logical operations: ADD, AND, NOT.  Yet students are expected to write code that does multiplication, division, modulus, XOR, OR, etc..!!  Multiplication & division/modulus are done with a loop; XOR and OR are done using logic sequences — we know all the boolean operation can be had using only NAND gates, so having (only) AND & NOT is primitive but sufficient.

    My favorite sequence for XOR on that processor comes from this formula:

    (A AND NOT B) + (NOT A AND B)
    

    Where here the + is literally ADD, which works as a substitute for OR because the two operands will never both be 1 at the same time, so carry from one bit position to another will not occur, and under those circumstances, ADD and OR are equivalent.

    0 讨论(0)
提交回复
热议问题