+/* Function: push_arguments
+ Setup the function arguments for calling a function in the inferior.
+
+ On the Hitachi H8/300 architecture, there are three registers (R0 to R2)
+ which are dedicated for passing function arguments. Up to the first
+ three arguments (depending on size) may go into these registers.
+ The rest go on the stack.
+
+ Arguments that are smaller than WORDSIZE bytes will still take up a
+ whole register or a whole WORDSIZE word on the stack, and will be
+ right-justified in the register or the stack word. This includes
+ chars and small aggregate types. Note that WORDSIZE depends on the
+ cpu type.
+
+ Arguments that are larger than WORDSIZE bytes will be split between
+ two or more registers as available, but will NOT be split between a
+ register and the stack.
+
+ An exceptional case exists for struct arguments (and possibly other
+ aggregates such as arrays) -- if the size is larger than WORDSIZE
+ bytes but not a multiple of WORDSIZE bytes. In this case the
+ argument is never split between the registers and the stack, but
+ instead is copied in its entirety onto the stack, AND also copied
+ into as many registers as there is room for. In other words, space
+ in registers permitting, two copies of the same argument are passed
+ in. As far as I can tell, only the one on the stack is used,
+ although that may be a function of the level of compiler
+ optimization. I suspect this is a compiler bug. Arguments of
+ these odd sizes are left-justified within the word (as opposed to
+ arguments smaller than WORDSIZE bytes, which are right-justified).
+
+ If the function is to return an aggregate type such as a struct,
+ the caller must allocate space into which the callee will copy the
+ return value. In this case, a pointer to the return value location
+ is passed into the callee in register R0, which displaces one of
+ the other arguments passed in via registers R0 to R2. */
+
+CORE_ADDR
+h8300_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ struct value **args;
+ CORE_ADDR sp;
+ unsigned char struct_return;
+ CORE_ADDR struct_addr;
+{
+ int stack_align, stack_alloc, stack_offset;
+ int wordsize;
+ int argreg;
+ int argnum;
+ struct type *type;
+ CORE_ADDR regval;
+ char *val;
+ char valbuf[4];
+ int len;
+
+ if (h8300hmode || h8300smode)
+ {
+ stack_align = 3;
+ wordsize = 4;
+ }
+ else
+ {
+ stack_align = 1;
+ wordsize = 2;
+ }
+
+ /* first force sp to a n-byte alignment */
+ sp = sp & ~stack_align;
+
+ /* Now make sure there's space on the stack */
+ for (argnum = 0, stack_alloc = 0;
+ argnum < nargs; argnum++)
+ stack_alloc += ((TYPE_LENGTH (VALUE_TYPE (args[argnum])) + stack_align)
+ & ~stack_align);
+ sp -= stack_alloc; /* make room on stack for args */
+ /* we may over-allocate a little here, but that won't hurt anything */
+
+ argreg = ARG0_REGNUM;
+ if (struct_return) /* "struct return" pointer takes up one argreg */
+ {
+ write_register (argreg++, struct_addr);
+ }
+
+ /* Now load as many as possible of the first arguments into
+ registers, and push the rest onto the stack. There are 3N bytes
+ in three registers available. Loop thru args from first to last. */
+
+ for (argnum = 0, stack_offset = 0; argnum < nargs; argnum++)
+ {
+ type = VALUE_TYPE (args[argnum]);
+ len = TYPE_LENGTH (type);
+ memset (valbuf, 0, sizeof (valbuf));
+ if (len < wordsize)
+ {
+ /* the purpose of this is to right-justify the value within the word */
+ memcpy (valbuf + (wordsize - len),
+ (char *) VALUE_CONTENTS (args[argnum]), len);
+ val = valbuf;
+ }
+ else
+ val = (char *) VALUE_CONTENTS (args[argnum]);
+
+ if (len > (ARGLAST_REGNUM + 1 - argreg) * REGISTER_RAW_SIZE (ARG0_REGNUM) ||
+ (len > wordsize && (len & stack_align) != 0))
+ { /* passed on the stack */
+ write_memory (sp + stack_offset, val,
+ len < wordsize ? wordsize : len);
+ stack_offset += (len + stack_align) & ~stack_align;
+ }
+ /* NOTE WELL!!!!! This is not an "else if" clause!!!
+ That's because some *&^%$ things get passed on the stack
+ AND in the registers! */
+ if (len <= (ARGLAST_REGNUM + 1 - argreg) * REGISTER_RAW_SIZE (ARG0_REGNUM))
+ while (len > 0)
+ { /* there's room in registers */
+ regval = extract_address (val, wordsize);
+ write_register (argreg, regval);
+ len -= wordsize;
+ val += wordsize;
+ argreg++;
+ }
+ }
+ return sp;
+}
+
+/* Function: push_return_address
+ Setup the return address for a dummy frame, as called by
+ call_function_by_hand. Only necessary when you are using an
+ empty CALL_DUMMY, ie. the target will not actually be executing
+ a JSR/BSR instruction. */
+
+CORE_ADDR
+h8300_push_return_address (pc, sp)
+ CORE_ADDR pc;
+ CORE_ADDR sp;
+{
+ unsigned char buf[4];
+ int wordsize;
+
+ if (h8300hmode || h8300smode)
+ wordsize = 4;
+ else
+ wordsize = 2;
+
+ sp -= wordsize;
+ store_unsigned_integer (buf, wordsize, CALL_DUMMY_ADDRESS ());
+ write_memory (sp, buf, wordsize);
+ return sp;
+}
+
+/* Function: pop_frame
+ Restore the machine to the state it had before the current frame
+ was created. Usually used either by the "RETURN" command, or by
+ call_function_by_hand after the dummy_frame is finished. */
+
+void