fix elwidth overrides when sw=8
[openpower-isa.git] / src / openpower / decoder / isa / caller.py
index 35d4db60ccaa5fdd52e1309abc47f173004a3fd7..9a8c24817c27f77ea51003ab2ecd1af39e271a93 100644 (file)
@@ -18,6 +18,7 @@ from copy import deepcopy
 from functools import wraps
 import os
 import sys
+from elftools.elf.elffile import ELFFile  # for isinstance
 
 from nmigen.sim import Settle
 import openpower.syscalls
@@ -25,7 +26,7 @@ from openpower.consts import (MSRb, PIb,  # big-endian (PowerISA versions)
                               SVP64CROffs, SVP64MODEb)
 from openpower.decoder.helpers import (ISACallerHelper, ISAFPHelpers, exts,
                                        gtu, undefined, copy_assign_rhs)
-from openpower.decoder.isa.mem import Mem, MemMMap, MemException
+from openpower.decoder.isa.mem import Mem, MemMMap, MemException, LoadedELF
 from openpower.decoder.isa.radixmmu import RADIX
 from openpower.decoder.isa.svshape import SVSHAPE
 from openpower.decoder.isa.svstate import SVP64State
@@ -245,7 +246,7 @@ class GPR(dict):
                 for j in range(8):
                     s.append("%08x" % res[i+j])
                 s = ' '.join(s)
-                print("reg", "%2d" % i, s)
+                log("reg", "%2d" % i, s, kind=LogType.InstrInOuts)
         return res
 
 
@@ -1144,6 +1145,10 @@ class StepLoop:
         log("    new dststep", dststep)
 
 
+class ExitSyscallCalled(Exception):
+    pass
+
+
 class SyscallEmulator(openpower.syscalls.Dispatcher):
     def __init__(self, isacaller):
         self.__isacaller = isacaller
@@ -1158,6 +1163,17 @@ class SyscallEmulator(openpower.syscalls.Dispatcher):
         (identifier, *arguments) = map(int, (identifier, *arguments))
         return super().__call__(identifier, *arguments)
 
+    def sys_exit_group(self, status, *rest):
+        self.__isacaller.halted = True
+        raise ExitSyscallCalled(status)
+
+    def sys_write(self, fd, buf, count, *rest):
+        buf = self.__isacaller.mem.get_ctypes(buf, count, is_write=False)
+        try:
+            return os.write(fd, buf)
+        except OSError as e:
+            return -e.errno
+
 
 class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
     # decoder2 - an instance of power_decoder2
@@ -1178,7 +1194,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
                  initial_fpscr=0,
                  insnlog=None,
                  use_mmap_mem=False,
-                 use_syscall_emu=False):
+                 use_syscall_emu=False,
+                 emulating_mmap=False):
         if use_syscall_emu:
             self.syscall = SyscallEmulator(isacaller=self)
             if not use_mmap_mem:
@@ -1187,6 +1204,16 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         else:
             self.syscall = None
 
+        # we will eventually be able to load ELF files without use_syscall_emu
+        # (e.g. the linux kernel), so do it in a separate if block
+        if isinstance(initial_insns, ELFFile):
+            if not use_mmap_mem:
+                log("forcing use_mmap_mem due to loading an ELF file")
+                use_mmap_mem = True
+            if not emulating_mmap:
+                log("forcing emulating_mmap due to loading an ELF file")
+                emulating_mmap = True
+
         # trace log file for model output. if None do nothing
         self.insnlog = insnlog
         self.insnlog_is_file = hasattr(insnlog, "write")
@@ -1257,9 +1284,15 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         if use_mmap_mem:
             self.mem = MemMMap(row_bytes=8,
                                initial_mem=initial_mem,
-                               misaligned_ok=True)
+                               misaligned_ok=True,
+                               emulating_mmap=emulating_mmap)
             self.imem = self.mem
-            self.mem.initialize(row_bytes=4, initial_mem=initial_insns)
+            lelf = self.mem.initialize(row_bytes=4, initial_mem=initial_insns)
+            if isinstance(lelf, LoadedELF):  # stuff parsed from ELF
+                initial_pc = lelf.pc
+                for k, v in lelf.gprs.items():
+                    self.gpr[k] = SelectableInt(v, 64)
+                initial_fpscr = lelf.fpscr
             self.mem.log_fancy(kind=LogType.InstrInOuts)
         else:
             self.mem = Mem(row_bytes=8, initial_mem=initial_mem,
@@ -2019,8 +2052,6 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         # 2. Call the HDL implementation which invokes trap.
         # 3. Reroute the guest system call to host system call.
         # 4. Force return from the interrupt as if we had guest OS.
-        #    "executing" rfid requires putting 0x4c000024 temporarily
-        #    into the program at the PC. TODO investigate and remove
         if ((asmop in ("sc", "scv")) and
                 (self.syscall is not None) and
                 not syscall_emu_active):
@@ -2038,10 +2069,8 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             self.gpr.write(3, result, False, self.namespace["XLEN"])
 
             # Return from interrupt
-            backup = self.imem.ld(pc, 4, False, True, instr_fetch=True)
-            self.imem.st(pc, 0x4c000024, width=4, swap=True)
             yield from self.call("rfid", syscall_emu_active=True)
-            self.imem.st(pc, backup, width=4, swap=True)
+            return
         elif ((name in ("rfid", "hrfid")) and syscall_emu_active):
             asmop = "rfid"
 
@@ -2059,7 +2088,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
                        "brh", "brw", "brd",
                        'setvl', 'svindex', 'svremap', 'svstep',
                        'svshape', 'svshape2',
-                       'ternlogi', 'bmask', 'cprop',
+                       'ternlogi', 'bmask', 'cprop', 'gbbd',
                        'absdu', 'absds', 'absdacs', 'absdacu', 'avgadd',
                        'fmvis', 'fishmv', 'pcdec', "maddedu", "divmod2du",
                        "dsld", "dsrd", "maddedus",
@@ -2075,6 +2104,11 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             illegal = False
             ins_name = dotstrp
 
+        # match against instructions treated as nop, see nop below
+        if asmop.startswith("dcbt"):
+            illegal = False
+            ins_name = "nop"
+
         # branch-conditional redirects to sv.bc
         if asmop.startswith('bc') and self.is_svp64_mode:
             ins_name = 'sv.%s' % ins_name
@@ -2120,7 +2154,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             ew_src = 8 << (3-int(ew_src))  # convert to bitlength
             ew_dst = 8 << (3-int(ew_dst))  # convert to bitlength
             xlen = max(ew_src, ew_dst)
-            log("elwdith", ew_src, ew_dst)
+            log("elwidth", ew_src, ew_dst)
         log("XLEN:", self.is_svp64_mode, xlen)
 
         # look up instruction in ISA.instrs, prepare namespace
@@ -2216,7 +2250,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             elif name in spr_byname:
                 inputs[name] = self.spr[name]
             else:
-                regval = (yield from self.get_input(name, ew_src))
+                regval = (yield from self.get_input(name, ew_src, xlen))
                 log("regval name", name, regval)
                 inputs[name] = regval
 
@@ -2516,7 +2550,7 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
             else:
                 self.namespace['D'] = imm
 
-    def get_input(self, name, ew_src):
+    def get_input(self, name, ew_src, xlen):
         # using PowerDecoder2, first, find the decoder index.
         # (mapping name RA RB RC RS to in1, in2, in3)
         regnum, is_vec = yield from get_idx_in(self.dec2, name, True)
@@ -2543,14 +2577,17 @@ class ISACaller(ISACallerHelper, ISAFPHelpers, StepLoop):
         if not self.is_svp64_mode or not self.pred_src_zero:
             log('reading reg %s %s' % (name, str(regnum)), is_vec)
             if name in fregs:
-                reg_val = SelectableInt(self.fpr(base, is_vec, offs, ew_src))
-                log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value),
-                    kind=LogType.InstrInOuts)
+                fval = self.fpr(base, is_vec, offs, ew_src)
+                reg_val = SelectableInt(fval)
+                assert ew_src == XLEN, "TODO fix elwidth conversion"
                 self.trace("r:FPR:%d:%d:%d " % (base, offs, ew_src))
+                log("read fp reg %d/%d: 0x%x" % (base, offs, reg_val.value),
+                    kind=LogType.InstrInOuts)
             elif name is not None:
-                reg_val = SelectableInt(self.gpr(base, is_vec, offs, ew_src))
+                gval = self.gpr(base, is_vec, offs, ew_src)
+                reg_val = SelectableInt(gval.value, bits=xlen)
                 self.trace("r:GPR:%d:%d:%d " % (base, offs, ew_src))
-                log("read reg %d/%d: 0x%x" % (base, offs, reg_val.value),
+                log("read int reg %d/%d: 0x%x" % (base, offs, reg_val.value),
                     kind=LogType.InstrInOuts)
         else:
             log('zero input reg %s %s' % (name, str(regnum)), is_vec)