diff options
Diffstat (limited to 'sim/h8300/compile.c')
-rw-r--r-- | sim/h8300/compile.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/sim/h8300/compile.c b/sim/h8300/compile.c index eb2a03f..54a0659 100644 --- a/sim/h8300/compile.c +++ b/sim/h8300/compile.c @@ -176,6 +176,17 @@ lvalue (int x, int rn) } } +static int +cmdline_location() +{ + if (h8300smode) + return 0xffff00L; + else if (h8300hmode) + return 0x2ff00L; + else + return 0xff00L; +} + static unsigned int decode (int addr, unsigned char *data, decoded_inst *dst) { @@ -477,6 +488,9 @@ decode (int addr, unsigned char *data, decoded_inst *dst) case 0xcb: dst->opcode = O (O_SYS_FSTAT, SB); break; + case 0xcc: + dst->opcode = O (O_SYS_CMDLINE, SB); + break; } /* End of Processing for system calls. */ } @@ -1410,6 +1424,163 @@ sim_resume (SIM_DESC sd, int step, int siggnal) goto condtrue; goto next; + /* Trap for Command Line setup. */ + case O (O_SYS_CMDLINE, SB): + { + int i = 0; /* Loop counter. */ + int j = 0; /* Loop counter. */ + int ind_arg_len = 0; /* Length of each argument. */ + int no_of_args = 0; /* The no. or cmdline args. */ + int current_location = 0; /* Location of string. */ + int old_sp = 0; /* The Initial Stack Pointer. */ + int no_of_slots = 0; /* No. of slots required on the stack + for storing cmdline args. */ + int sp_move = 0; /* No. of locations by which the stack needs + to grow. */ + int new_sp = 0; /* The final stack pointer location passed + back. */ + int *argv_ptrs; /* Pointers of argv strings to be stored. */ + int argv_ptrs_location = 0; /* Location of pointers to cmdline + args on the stack. */ + int char_ptr_size = 0; /* Size of a character pointer on + target machine. */ + int addr_cmdline = 0; /* Memory location where cmdline has + to be stored. */ + int size_cmdline = 0; /* Size of cmdline. */ + + /* Set the address of 256 free locations where command line is + stored. */ + addr_cmdline = cmdline_location(); + cpu.regs[0] = addr_cmdline; + + /* Counting the no. of commandline arguments. */ + for (i = 0; ptr_command_line[i] != NULL; i++) + continue; + + /* No. of arguments in the command line. */ + no_of_args = i; + + /* Current location is just a temporary variable,which we are + setting to the point to the start of our commandline string. */ + current_location = addr_cmdline; + + /* Allocating space for storing pointers of the command line + arguments. */ + argv_ptrs = (int *) malloc (sizeof (int) * no_of_args); + + /* Setting char_ptr_size to the sizeof (char *) on the different + architectures. */ + if (h8300hmode || h8300smode) + { + char_ptr_size = 4; + } + else + { + char_ptr_size = 2; + } + + for (i = 0; i < no_of_args; i++) + { + ind_arg_len = 0; + + /* The size of the commandline argument. */ + ind_arg_len = (strlen (ptr_command_line[i]) + 1); + + /* The total size of the command line string. */ + size_cmdline += ind_arg_len; + + /* As we have only 256 bytes, we need to provide a graceful + exit. Anyways, a program using command line arguments + where we cannot store all the command line arguments + given may behave unpredictably. */ + if (size_cmdline >= 256) + { + cpu.regs[0] = 0; + goto next; + } + else + { + /* current_location points to the memory where the next + commandline argument is stored. */ + argv_ptrs[i] = current_location; + for (j = 0; j < ind_arg_len; j++) + { + SET_MEMORY_B ((current_location + + (sizeof (char) * j)), + *(ptr_command_line[i] + + sizeof (char) * j)); + } + + /* Setting current_location to the starting of next + argument. */ + current_location += ind_arg_len; + } + } + + /* This is the original position of the stack pointer. */ + old_sp = cpu.regs[7]; + + /* We need space from the stack to store the pointers to argvs. */ + /* As we will infringe on the stack, we need to shift the stack + pointer so that the data is not overwritten. We calculate how + much space is required. */ + sp_move = (no_of_args) * (char_ptr_size); + + /* The final position of stack pointer, we have thus taken some + space from the stack. */ + new_sp = old_sp - sp_move; + + /* Temporary variable holding value where the argv pointers need + to be stored. */ + argv_ptrs_location = new_sp; + + /* The argv pointers are stored at sequential locations. As per + the H8300 ABI. */ + for (i = 0; i < no_of_args; i++) + { + /* Saving the argv pointer. */ + if (h8300hmode || h8300smode) + { + SET_MEMORY_L (argv_ptrs_location, argv_ptrs[i]); + } + else + { + SET_MEMORY_W (argv_ptrs_location, argv_ptrs[i]); + } + + /* The next location where the pointer to the next argv + string has to be stored. */ + argv_ptrs_location += char_ptr_size; + } + + /* Required by POSIX, Setting 0x0 at the end of the list of argv + pointers. */ + if (h8300hmode || h8300smode) + { + SET_MEMORY_L (old_sp, 0x0); + } + else + { + SET_MEMORY_W (old_sp, 0x0); + } + + /* Freeing allocated memory. */ + free (argv_ptrs); + for (i = 0; i <= no_of_args; i++) + { + free (ptr_command_line[i]); + } + free (ptr_command_line); + + /* The no. of argv arguments are returned in Reg 0. */ + cpu.regs[0] = no_of_args; + /* The Pointer to argv in Register 1. */ + cpu.regs[1] = new_sp; + /* Setting the stack pointer to the new value. */ + cpu.regs[7] = new_sp; + } + goto next; + /* System call processing starts. */ case O (O_SYS_OPEN, SB): { @@ -2531,10 +2702,37 @@ sim_load (SIM_DESC sd, char *prog, bfd *abfd, int from_tty) SIM_RC sim_create_inferior (SIM_DESC sd, struct bfd *abfd, char **argv, char **env) { + int i = 0; + int len_arg = 0; + int no_of_args = 0; + if (abfd != NULL) cpu.pc = bfd_get_start_address (abfd); else cpu.pc = 0; + + /* Command Line support. */ + if (argv != NULL) + { + /* Counting the no. of commandline arguments. */ + for (no_of_args = 0; argv[no_of_args] != NULL; no_of_args++) + continue; + + /* Allocating memory for the argv pointers. */ + ptr_command_line = (char **) malloc ((sizeof (char *)) + * (no_of_args + 1)); + + for (i = 0; i < no_of_args; i++) + { + /* Calculating the length of argument for allocating memory. */ + len_arg = strlen (argv[i] + 1); + ptr_command_line[i] = (char *) malloc (sizeof (char) * len_arg); + /* Copying the argument string. */ + ptr_command_line[i] = (char *) strdup (argv[i]); + } + ptr_command_line[i] = NULL; + } + return SIM_RC_OK; } |