-/* EXPAND_BUILTIN_VA_ARG. */
-
-/* This is modified from the "standard" implementation of va_arg: read the
- value from the current (padded) address and increment by the (padded)
- size. The difference for MMIX is that if the type is
- pass-by-reference, then perform an indirection. */
-
-rtx
-mmix_expand_builtin_va_arg (valist, type)
- tree valist;
- tree type;
-{
- tree ptr_size = size_int (BITS_PER_WORD / BITS_PER_UNIT);
- tree addr_tree, type_size = NULL;
- tree align, alignm1;
- tree rounded_size;
- rtx addr;
-
- /* Compute the rounded size of the type. */
-
- /* Get AP. */
- addr_tree = valist;
- align = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
- alignm1 = size_int (PARM_BOUNDARY / BITS_PER_UNIT - 1);
- if (type == error_mark_node
- || (type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type))) == NULL
- || TREE_OVERFLOW (type_size))
- /* Presumably an error; the size isn't computable. A message has
- supposedly been emitted elsewhere. */
- rounded_size = size_zero_node;
- else
- rounded_size = fold (build (MULT_EXPR, sizetype,
- fold (build (TRUNC_DIV_EXPR, sizetype,
- fold (build (PLUS_EXPR, sizetype,
- type_size, alignm1)),
- align)),
- align));
-
- if (AGGREGATE_TYPE_P (type)
- && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) < 8
- && GET_MODE_UNIT_SIZE (TYPE_MODE (type)) != 0)
- {
- /* Adjust for big-endian the location of aggregates passed in a
- register, but where the aggregate is accessed in a shorter mode
- than the natural register mode (i.e. it is accessed as SFmode(?),
- SImode, HImode or QImode rather than DImode or DFmode(?)). FIXME:
- Or should we adjust the mode in which the aggregate is read, to be
- a register size mode? (Hum, nah, a small offset is generally
- cheaper than a wider memory access on MMIX.) */
- addr_tree
- = build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
- size_int ((BITS_PER_WORD / BITS_PER_UNIT)
- - GET_MODE_UNIT_SIZE (TYPE_MODE (type))));
- }
- else if (!integer_zerop (rounded_size))
- {
- if (!really_constant_p (type_size))
- /* Varying-size types come in by reference. */
- addr_tree
- = build1 (INDIRECT_REF, build_pointer_type (type), addr_tree);
- else
- {
- /* If the size is less than a register, then we need to pad the
- address by adding the difference. */
- tree addend
- = fold (build (COND_EXPR, sizetype,
- fold (build (GT_EXPR, sizetype,
- rounded_size,
- align)),
- size_zero_node,
- fold (build (MINUS_EXPR, sizetype,
- rounded_size,
- type_size))));
- tree addr_tree1
- = fold (build (PLUS_EXPR, TREE_TYPE (addr_tree), addr_tree,
- addend));
-
- /* If this type is larger than what fits in a register, then it
- is passed by reference. */
- addr_tree
- = fold (build (COND_EXPR, TREE_TYPE (addr_tree1),
- fold (build (GT_EXPR, sizetype,
- rounded_size,
- ptr_size)),
- build1 (INDIRECT_REF, build_pointer_type (type),
- addr_tree1),
- addr_tree1));
- }
- }
-
- addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
- addr = copy_to_reg (addr);
-
- if (!integer_zerop (rounded_size))
- {
- /* Compute new value for AP. For MMIX, it is always advanced by the
- size of a register. */
- tree t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
- build (PLUS_EXPR, TREE_TYPE (valist), valist,
- ptr_size));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
-
- return addr;
-}
-
-/* TRAMPOLINE_SIZE. */
-/* Four 4-byte insns plus two 8-byte values. */
-int mmix_trampoline_size = 32;
-
-
-/* TRAMPOLINE_TEMPLATE. */
-
-void
-mmix_trampoline_template (stream)
- FILE * stream;
-{
- /* Read a value into the static-chain register and jump somewhere. The
- static chain is stored at offset 16, and the function address is
- stored at offset 24. */
- /* FIXME: GCC copies this using *intsize* (tetra), when it should use
- register size (octa). */
- fprintf (stream, "\tGETA $255,1F\n\t");
- fprintf (stream, "LDOU %s,$255,0\n\t",
- reg_names[MMIX_STATIC_CHAIN_REGNUM]);
- fprintf (stream, "LDOU $255,$255,8\n\t");
- fprintf (stream, "GO $255,$255,0\n");
- fprintf (stream, "1H\tOCTA 0\n\t");
- fprintf (stream, "OCTA 0\n");
-}
-
-/* INITIALIZE_TRAMPOLINE. */
-/* Set the static chain and function pointer field in the trampoline.
- We also SYNCID here to be sure (doesn't matter in the simulator, but
- some day it will). */
-
-void
-mmix_initialize_trampoline (trampaddr, fnaddr, static_chain)
- rtx trampaddr;
- rtx fnaddr;
- rtx static_chain;
-{
- emit_move_insn (gen_rtx_MEM (DImode, plus_constant (trampaddr, 16)),
- static_chain);
- emit_move_insn (gen_rtx_MEM (DImode,
- plus_constant (trampaddr, 24)),
- fnaddr);
- emit_insn (gen_sync_icache (validize_mem (gen_rtx_MEM (DImode,
- trampaddr)),
- GEN_INT (mmix_trampoline_size - 1)));
-}
-
-/* We must exclude constant addresses that have an increment that is not a
- multiple of four bytes because of restrictions of the GETA
- instruction, unless TARGET_BASE_ADDRESSES. */
-
-int
-mmix_constant_address_p (x)
- rtx x;