Homemade operating system: risc-v loading storage instructions

Posted by m0rpheu5 on Mon, 28 Feb 2022 13:12:05 +0100

Load instruction

Instruction name

function

ISA

type

usage

meaning

LA

Address loading, pseudo instruction

RV32I/RV64I 

Pseudo instruction

la rd, symbol

Load the address of the symbol into x[rd]. When compiling location independent code, it is extended to the global offset table

(Global Offset Table). For RV32I, it is equivalent to executing auipc rd, offsetHi, and then lw rd,

offsetLo(rd); For RV64I, it is equivalent to auipc rd, offsetHi and ld rd, offsetLo(rd). If the offset is too large,

The first instruction to calculate the load address will become two, first auipc rd, offsetHi, and then addi Rd, RD, and offsetlo

LI

Immediate load,

RV32I/RV64I 

Pseudo instruction

li rd, immediate

Load constants into x[rd] with as few instructions as possible. In RV32I, it is equivalent to executing lui and / or addi; yes

In RV64I, it will be extended to this instruction sequence Lui, addi, slli, addi, slli, addi, slli, addi.

LLA

Local address loading, pseudo instruction

RV32I/RV64I

Pseudo instruction

lla rd, symbol

Load the address of the symbol into x[rd]. It is equivalent to executing auipc rd, offsetHi, and then addi rd, rd, offsetLo.

LB

Byte loading

RV32I/RV64I 

I

lb rd, offset(rs1)

Read a byte from address x [RS1] + sign extend (offset) and write it to x[rd] after symbol bit expansion.

LBU

Unsigned byte loading

RV32I/RV64I

I

lbu rd, offset(rs1)

Read a byte from the address x [RS1] + sign extend (offset) and write it to x[rd] after zero expansion.

LH

Half word loading

RV32I/RV64I

I

lh rd, offset(rs1)

Read two bytes from address x [RS1] + sign extend (offset), and write x[rd] after symbol bit expansion.

LHU

Unsigned halfword loading

RV32I/RV64I

I

lhu rd, offset(rs1)

Read two bytes from address x [RS1] + sign extend (offset), and write x[rd] after zero expansion.

LD

Double word loading

RV32I/RV64I

I

ld rd, offset(rs1)

Read eight bytes from address x [RS1] + sign extend (offset) and write x[rd].

LR.D

Load reserved doubleword

RV64A 

R

lr.d rd, (rs1)

Load eight bytes from the memory address x[rs1], write x[rd], and reserve the memory doubleword registration

LW

Word loading

RV32I/RV64I

I

lw rd, offset(rs1)

Read four bytes from address x [RS1] + sign extend (offset) and write x[rd]. For RV64I, the results are signed

Bit extension.

LR.W

Load reserved words

RV32A/RV64A

R

lr.w rd, (rs1)

Load four bytes from the address x[rs1] in memory, write x[rd] after symbol bit expansion, and register and reserve this memory word.

LWU

Unsigned word loading

RV64I

I

lwu rd, offset(rs1)

Read four bytes from address x [RS1] + sign extend (offset), and write x[rd] after zero expansion.

LUI

High immediate load

RV32I/RV64I

U

lui rd, immediate

Shift the sign bit extended 20 bit immediate to the left by 12 bits, and write the low 12 position zero into x[rd].

Exercise: learn the usage of LA/LB/LD/LH/LHU instruction

#
# Learn the usage of la and lb instructions:
# Function char load_isa_la_lb(int index)
# Function meaning:
#   la loads the address of msg into the s2 register, and the parameter index is represented by a0 in the assembly
#   Then use the lb instruction to read the index byte of msg string, and the return value is stored in a0.
# Summary:
#    la address loading instruction, pseudo instruction, usage la rd, symbol, load symbol into x[rd] register
#    lb byte loading instruction, lb rd, offset(rs1), read a byte from address x [RS1] + sign extend (offset)
.globl load_isa_la_lb
load_isa_la_lb:
    la s2, msg
    add s3, s2, a0
    lb a0, 0(s3)
    ret

#
# Function unsigned long load_isa_ld(unsigned long *array, int index)
# Function meaning:
#   Returns the value of array[index].
#   The value of array is stored in register a0 and the value of index is stored in register a1
#   slli logical shift left instruction shifts the value of index by 3 bits to the left, which is equivalent to multiplying by 8
# Summary:
#   1. In the compilation, index is only a numerical value and will not be intelligently converted into array[index],
#   You must convert it to array+8*index to get the value of array[index]
#   2. The LD instruction is a double word loading instruction in the format of LD, RD, offset (RS1) 
#        Read 8 bytes from address x [RS1] + sign extend (offset) and write x[rd]

.globl load_isa_ld
load_isa_ld:
    slli a1, a1, 3 # a1*8
    add s1, a0, a1
    ld a0, 0(s1)
    ret
#
# Function unsigned int load_isa_lh(unsigned int *array, int index)
#  load_isa_lh and load_ isa_ The lhu function is used to compare lh and lhu instructions
#   LH: LH Rd offset (RS1) half word loading instruction, read 2 bytes from address x [RS1] + sign extend (offset), and write x[rd] after symbol bit expansion
#   lhu: lhu rd offset(rs1) unsigned halfword loading instruction, read 2 bytes from address x [RS1] + sign extend (offset), and write x[rd] after symbol bit expansion
.globl load_isa_lh
load_isa_lh:
    slli a1, a1, 2 # a1*4
    add s1, a0, a1
    lh a0, 0(s1)
    ret

#
# Function unsigned int load_isa_lhu(unsigned int *array, int index)
#
.globl load_isa_lhu
load_isa_lhu:
    slli a1, a1, 2 # a1*4
    add s1, a0, a1
    lhu a0, 0(s1)
    ret

.section .data
msg:
  .string "Hello, world!\n"

Storage instruction

Instruction name

function

ISA

type

usage

meaning

SD

Save double word

RV64I

S

sd rs2, offset(rs1)

Store the 8 bytes in x[rs2] into the memory address x [RS1] + sign extend (offset).

SC.D

Conditional deposit double word

RV64A

R

sc.d rd, rs2, (rs1)

If there is a load reservation on the memory address x[rs1], store the number of 8 bytes in the x[rs2] register in that address. If deposited

If successful, store 0 in register x[rd], otherwise store a non-0 error code

SW

Save word

RV32I/RV64I

S

sw rs2, offset(rs1)

Store the lower 4 bytes of x[rs2] into the memory address x [RS1] + sign extend (offset).

SC.W

Conditional deposit word

RV32A/RV64A

R

sc.w rd, rs2, (rs1)

There is a load reservation on the memory address x[rs1], and the number of 4 bytes in the x[rs2] register is stored in this address. If the deposit is successful,

Store 0 in register x[rd], otherwise store a non-0 error code.

SH

Save half word

RV32I/RV64I

S

sh rs2, offset(rs1)

Store the lower two bytes of x[rs2] into the memory address x [RS1] + sign extend (offset).

SB

Memory byte

RV32I/RV64I

S

sb rs2, offset(rs1)

Store the low byte of x[rs2] into the memory address x [RS1] + sign extend (offset).

Exercise: Learn SD/SW/SH/SB instructions

#
#  unsigned long store_isa_sd(unsigned long *addr, unsigned long v)
#  Function meaning:
#       Store v in the address addr, and then read the value of the data in addr memory and return
#
.globl store_isa_sd
store_isa_sd:
    sd a1, 0(a0)
    ld a0, 0(a0)
    ret

#  unsigned int store_isa_sd(unsigned int *addr, unsigned int v)
.globl store_isa_sw
store_isa_sw:
    sw a1, 0(a0)
    lw a0, 0(a0)
    ret

#  unsigned short store_isa_sd(unsigned short *addr, unsigned short v)
.globl store_isa_sh
store_isa_sh:
    sh a1, 0(a0)
    lh a0, 0(a0)    
    ret

#  unsigned char store_isa_sd(unsigned short *char, unsigned char v)
.globl store_isa_sb
store_isa_sb:
    sb a1, 0(a0)
    lb a0, 0(a0)   
    ret

Note that LR/SC can be used to construct lock free data structures.

Compare exchange functions as follows:

# a0 holds address of memory location
# a1 holds expected value
# a2 holds desired value
# a0 holds return value, 0 if successful, !0 otherwise
cas:
    lr.w t0, (a0)
    bne t0, a1, fail
    sc.w t0, a2, (a0)
    bnez t0, cas
    li a0, 0
    jr ra
fail:
    li a0, 1
    jr ra
# Load original value.
# Doesn't match, so fail.
# Try to update.
# Retry if store-conditional failed.
# Set return to success.
# Return.
# Set return to failure.
# Return.

Assembly reference code

Call assembly code

Topics: risc-v