[otbn] Add support for the "la" pseudo-operation to otbn-as
Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/data/base-insns.yml b/hw/ip/otbn/data/base-insns.yml
index 24a531f..9d1d5ce 100644
--- a/hw/ip/otbn/data/base-insns.yml
+++ b/hw/ip/otbn/data/base-insns.yml
@@ -501,6 +501,15 @@
followed by an ADDI).
python-pseudo-op: true
+- mnemonic: la
+ synopsis: Load absolute address
+ rv32i: true
+ operands: [grd, imm]
+ doc: |
+ Loads an address given by a symbol into a GPR. This is represented
+ as a LUI and an ADDI.
+ python-pseudo-op: true
+
- mnemonic: ret
synopsis: Return from subroutine
rv32i: true
diff --git a/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/bigla.exp b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/bigla.exp
new file mode 100644
index 0000000..047706b
--- /dev/null
+++ b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/bigla.exp
@@ -0,0 +1,6 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+x2 = 2048
+x3 = 0x1234
diff --git a/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/bigla.s b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/bigla.s
new file mode 100644
index 0000000..15db594
--- /dev/null
+++ b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/bigla.s
@@ -0,0 +1,16 @@
+/* Copyright lowRISC contributors. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+/*
+ Checks for "la" pseudo-instruction support where the symbol is too big to
+ fit in a signed immediate for addi.
+*/
+.text
+ la x2, foo
+ lw x3, 0(x2)
+ ecall
+
+.data
+.org 2048
+foo:
+ .word 0x1234
diff --git a/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/la.exp b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/la.exp
new file mode 100644
index 0000000..eba3151
--- /dev/null
+++ b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/la.exp
@@ -0,0 +1,9 @@
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+x2 = 0
+x3 = 4
+x4 = 0x1234
+x5 = 0x5678
+x6 = 0
diff --git a/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/la.s b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/la.s
new file mode 100644
index 0000000..f95a710
--- /dev/null
+++ b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/la.s
@@ -0,0 +1,19 @@
+/* Copyright lowRISC contributors. */
+/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
+/* SPDX-License-Identifier: Apache-2.0 */
+/*
+ Checks for "la" pseudo-instruction support
+*/
+.data
+foo:
+ .word 0x1234
+
+bar:
+ .word 0x5678
+
+.text
+ la x2, foo
+ la x3, bar
+ lw x4, 0(x2)
+ lw x5, 0(x3)
+ ecall
diff --git a/hw/ip/otbn/dv/otbnsim/test/simple/insns/li.exp b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/li.exp
similarity index 100%
rename from hw/ip/otbn/dv/otbnsim/test/simple/insns/li.exp
rename to hw/ip/otbn/dv/otbnsim/test/simple/pseudos/li.exp
diff --git a/hw/ip/otbn/dv/otbnsim/test/simple/insns/li.s b/hw/ip/otbn/dv/otbnsim/test/simple/pseudos/li.s
similarity index 100%
rename from hw/ip/otbn/dv/otbnsim/test/simple/insns/li.s
rename to hw/ip/otbn/dv/otbnsim/test/simple/pseudos/li.s
diff --git a/hw/ip/otbn/util/otbn-as b/hw/ip/otbn/util/otbn-as
index 9122884..5d8958e 100755
--- a/hw/ip/otbn/util/otbn-as
+++ b/hw/ip/otbn/util/otbn-as
@@ -455,19 +455,17 @@
return (positionals, others, flags)
-def expand_li(where: str, op_to_expr: Dict[str, Optional[str]]) -> List[str]:
- '''Expand the li pseudo-op'''
-
- # This logic is slightly complicated so it has some associated tests in the
- # ISS testsuite (where we can run the results). If adding more cleverness
- # to this or fixing bugs, we should also add a check at
- # hw/ip/otbn/dv/otbnsim/test/simple/li.
-
+def _unpack_lx(where: str,
+ mnemonic: str,
+ op_to_expr: Dict[str, Optional[str]]) -> Tuple[str, str]:
+ '''Unpack the arguments to li or la'''
if set(op_to_expr.keys()) != {'grd', 'imm'}:
- raise RuntimeError('When expanding LI, got wrong op_to_expr keys '
- '({}). This is a mismatch between expand_li in '
- 'otbn-as and the operands for LI in insns.yml.'
- .format(list(op_to_expr.keys())))
+ umnem = mnemonic.upper()
+ keys_list = list(op_to_expr.keys())
+ raise RuntimeError(f'When expanding {umnem}, got wrong op_to_expr '
+ f'keys ({keys_list}). This is a mismatch between '
+ f'expand_{mnemonic} in otbn-as and the operands '
+ f'for {umnem} in insns.yml.')
grd = op_to_expr['grd']
imm = op_to_expr['imm']
@@ -490,7 +488,18 @@
.format(where, err))
grd_txt = gpr_type.op_val_to_str(grd_op_val, None)
+ return (grd_txt, imm)
+
+def expand_li(where: str, op_to_expr: Dict[str, Optional[str]]) -> List[str]:
+ '''Expand the li pseudo-op'''
+
+ # This logic is slightly complicated so it has some associated tests in the
+ # ISS testsuite (where we can run the results). If adding more cleverness
+ # to this or fixing bugs, we should also add a check at
+ # hw/ip/otbn/dv/otbnsim/test/simple/pseudos/li.s.
+
+ grd_txt, imm = _unpack_lx(where, 'li', op_to_expr)
try:
imm_int = int(imm, 0)
except ValueError:
@@ -542,8 +551,30 @@
'addi {}, {}, {}'.format(grd_txt, grd_txt, imm_12)]
+def expand_la(where: str, op_to_expr: Dict[str, Optional[str]]) -> List[str]:
+ '''Expand the la pseudo-op'''
+
+ # For RISC-V, "la rd, symbol" expands to two instructions:
+ #
+ # auipc rd, delta[31:12] + delta[11]
+ # addi rd, rd, delta[11:0]
+ #
+ # where delta = symbol - pc.
+ #
+ # For OTBN, both IMEM and DMEM are small. This means that we can represent
+ # every symbol in 12 bits, so "la rd, symbol" can expand to:
+ #
+ # addi rd, x0, %lo(symbol)
+ #
+ # Much easier!
+ grd_txt, imm = _unpack_lx(where, 'la', op_to_expr)
+ return ['lui {}, %hi({})'.format(grd_txt, imm),
+ 'addi {}, {}, %lo({})'.format(grd_txt, grd_txt, imm)]
+
+
_PSEUDO_OP_ASSEMBLERS = {
- 'li': expand_li
+ 'li': expand_li,
+ 'la': expand_la
}