target/xtensa: fix semihosting argc/argv implementation
authorMax Filippov <jcmvbkbc@gmail.com>
Sat, 11 Mar 2017 19:24:45 +0000 (11:24 -0800)
committerMax Filippov <jcmvbkbc@gmail.com>
Sat, 11 Mar 2017 22:59:03 +0000 (14:59 -0800)
So far xtensa provides fixed dummy argc/argv for the corresponding
semihosting calls. Now that there are semihosting_get_argc and
semihosting_get_arg, use them to pass actual command line arguments
to guest.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
target/xtensa/xtensa-semi.c

index 370e365c65c0923a84227ba31bbce42231bd81f2..a888a9dc7b43a3bfda30f16985365bb935768750 100644 (file)
@@ -28,6 +28,7 @@
 #include "qemu/osdep.h"
 #include "cpu.h"
 #include "exec/helper-proto.h"
+#include "exec/semihost.h"
 #include "qemu/log.h"
 
 enum {
@@ -261,28 +262,50 @@ void HELPER(simcall)(CPUXtensaState *env)
         break;
 
     case TARGET_SYS_argc:
-        regs[2] = 1;
+        regs[2] = semihosting_get_argc();
         regs[3] = 0;
         break;
 
     case TARGET_SYS_argv_sz:
-        regs[2] = 128;
-        regs[3] = 0;
+        {
+            int argc = semihosting_get_argc();
+            int sz = (argc + 1) * sizeof(uint32_t);
+            int i;
+
+            for (i = 0; i < argc; ++i) {
+                sz += 1 + strlen(semihosting_get_arg(i));
+            }
+            regs[2] = sz;
+            regs[3] = 0;
+        }
         break;
 
     case TARGET_SYS_argv:
         {
-            struct Argv {
-                uint32_t argptr[2];
-                char text[120];
-            } argv = {
-                {0, 0},
-                "test"
-            };
-
-            argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
+            int argc = semihosting_get_argc();
+            int str_offset = (argc + 1) * sizeof(uint32_t);
+            int i;
+            uint32_t argptr;
+
+            for (i = 0; i < argc; ++i) {
+                const char *str = semihosting_get_arg(i);
+                int str_size = strlen(str) + 1;
+
+                argptr = tswap32(regs[3] + str_offset);
+
+                cpu_memory_rw_debug(cs,
+                                    regs[3] + i * sizeof(uint32_t),
+                                    (uint8_t *)&argptr, sizeof(argptr), 1);
+                cpu_memory_rw_debug(cs,
+                                    regs[3] + str_offset,
+                                    (uint8_t *)str, str_size, 1);
+                str_offset += str_size;
+            }
+            argptr = 0;
             cpu_memory_rw_debug(cs,
-                                regs[3], (uint8_t *)&argv, sizeof(argv), 1);
+                                regs[3] + i * sizeof(uint32_t),
+                                (uint8_t *)&argptr, sizeof(argptr), 1);
+            regs[3] = 0;
         }
         break;