/*
 * Utility to generate asm-ia64/offsets.h.
 *
 * Copyright (C) 1999-2000 Hewlett-Packard Co
 * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
 *
 * Note that this file has dual use: when building the kernel
 * natively, the file is translated into a binary and executed.  When
 * building the kernel in a cross-development environment, this file
 * gets translated into an assembly file which, in turn, is processed
 * by awk to generate offsets.h.  So if you make any changes to this
 * file, be sure to verify that the awk procedure still works (see
 * prin_offsets.awk).
 */
#include <linux/sched.h>

#include <asm-ia64/processor.h>
#include <asm-ia64/ptrace.h>
#include <asm-ia64/siginfo.h>
#include <asm-ia64/sigcontext.h>

#ifdef offsetof
# undef offsetof
#endif

/*
 * We _can't_ include the host's standard header file, as those are in
 *  potential conflict with the what the Linux kernel declares for the
 *  target system.
 */
extern int printf (const char *, ...);

#define offsetof(type,field)	((char *) &((type *) 0)->field - (char *) 0)

struct
  {
    const char name[256];
    unsigned long value;
  }
tab[] =
  {
    { "IA64_TASK_SIZE",			sizeof (struct task_struct) },
    { "IA64_PT_REGS_SIZE",		sizeof (struct pt_regs) },
    { "IA64_SWITCH_STACK_SIZE",		sizeof (struct switch_stack) },
    { "IA64_SIGINFO_SIZE",		sizeof (struct siginfo) },
    { "", 0 },			/* spacer */
    { "IA64_TASK_FLAGS_OFFSET",		offsetof (struct task_struct, flags) },
    { "IA64_TASK_SIGPENDING_OFFSET",	offsetof (struct task_struct, sigpending) },
    { "IA64_TASK_NEED_RESCHED_OFFSET",	offsetof (struct task_struct, need_resched) },
    { "IA64_TASK_PROCESSOR_OFFSET",	offsetof (struct task_struct, processor) },
    { "IA64_TASK_THREAD_OFFSET",	offsetof (struct task_struct, thread) },
    { "IA64_TASK_THREAD_KSP_OFFSET",	offsetof (struct task_struct, thread.ksp) },
    { "IA64_TASK_PID_OFFSET",		offsetof (struct task_struct, pid) },
    { "IA64_TASK_MM_OFFSET",		offsetof (struct task_struct, mm) },
    { "IA64_PT_REGS_CR_IPSR_OFFSET",	offsetof (struct pt_regs, cr_ipsr) },
    { "IA64_PT_REGS_R12_OFFSET",	offsetof (struct pt_regs, r12) },
    { "IA64_PT_REGS_R8_OFFSET",		offsetof (struct pt_regs, r8) },
    { "IA64_PT_REGS_R16_OFFSET",	offsetof (struct pt_regs, r16) },
    { "IA64_SWITCH_STACK_B0_OFFSET",	offsetof (struct switch_stack, b0) },
    { "IA64_SWITCH_STACK_CALLER_UNAT_OFFSET", offsetof (struct switch_stack, caller_unat) },
    { "IA64_SIGCONTEXT_AR_BSP_OFFSET",	offsetof (struct sigcontext, sc_ar_bsp) },
    { "IA64_SIGCONTEXT_AR_RNAT_OFFSET",	offsetof (struct sigcontext, sc_ar_rnat) },
    { "IA64_SIGCONTEXT_FLAGS_OFFSET",	offsetof (struct sigcontext, sc_flags) },
    { "IA64_SIGCONTEXT_CFM_OFFSET",	offsetof (struct sigcontext, sc_cfm) },
    { "IA64_SIGCONTEXT_FR6_OFFSET",	offsetof (struct sigcontext, sc_fr[6]) },
};

static const char *tabs = "\t\t\t\t\t\t\t\t\t\t";

int
main (int argc, char **argv)
{
  const char *space;
  int i, num_tabs;
  size_t len;

  printf ("#ifndef _ASM_IA64_OFFSETS_H\n");
  printf ("#define _ASM_IA64_OFFSETS_H\n\n");

  printf ("/*\n * DO NOT MODIFY\n *\n * This file was generated by "
	  "arch/ia64/tools/print_offsets.\n *\n */\n\n");

  /* This is stretching things a bit, but entry.S needs the bit number
     for PF_PTRACED and it can't include <linux/sched.h> so this seems
     like a reasonably solution.  At least the code won't break shoudl
     PF_PTRACED ever change.  */
  printf ("#define PF_PTRACED_BIT\t\t\t%u\n\n", ffs (PF_PTRACED) - 1);

  for (i = 0; i < sizeof (tab) / sizeof (tab[0]); ++i)
    {
      if (tab[i].name[0] == '\0')
	printf ("\n");
      else
	{
	  len = strlen (tab[i].name);

	  num_tabs = (40 - len) / 8;
	  if (num_tabs <= 0)
	    space = " ";
	  else
	    space = strchr(tabs, '\0') - (40 - len) / 8;

	  printf ("#define %s%s%lu\t/* 0x%lx */\n",
		  tab[i].name, space, tab[i].value, tab[i].value);
	}
    }

  printf ("\n#endif /* _ASM_IA64_OFFSETS_H */\n");
  return 0;
}
