#! /usr/bin/perl
#
#  TOPPERS/JSP Kernel
#      Toyohashi Open Platform for Embedded Real-Time Systems/
#      Just Standard Profile Kernel
# 
#  Copyright (C) 2000,2001 by Embedded and Real-Time Systems Laboratory
#                              Toyohashi Univ. of Technology, JAPAN
# 
#  嵭ԤϡFree Software Foundation ˤäƸɽƤ 
#  GNU General Public License  Version 2 ˵ҤƤ狼
#  ξΤ줫˸¤ꡤܥեȥܥեȥ
#  ѤΤޤࡥʲƱˤѡʣѡۡʰʲ
#  ѤȸƤ֡ˤ뤳Ȥ̵ǵ롥
#  (1) ܥեȥ򥽡ɤηѤˤϡ嵭
#      ɽѾ浪Ӳ̵ݾڵ꤬Τޤޤηǥ
#      ˴ޤޤƤ뤳ȡ
#  (2) ܥեȥѲǽʥХʥꥳɡʥ֥륪
#      ȥե饤֥ʤɡˤηѤˤϡ
#      ȼɥȡѼԥޥ˥奢ʤɡˤˡ嵭ɽ
#      Ѿ浪Ӳ̵ݾڵǺܤ뤳ȡ
#  (3) ܥեȥԲǽʥХʥꥳɤηޤϵ
#      ߹ѤˤϡΤ줫ξȡ
#    (a) ѤȼɥȡѼԥޥ˥奢ʤɡˤˡ嵭
#        ɽѾ浪Ӳ̵ݾڵǺܤ뤳ȡ
#    (b) Ѥη֤̤ˡˤäơ嵭Ԥ𤹤
#        ȡ
#  (4) ܥեȥѤˤľŪޤϴŪ뤤ʤ»
#      ⡤嵭Ԥդ뤳ȡ
# 
#  ܥեȥϡ̵ݾڤ󶡤ƤΤǤ롥嵭Ԥϡ
#  ܥեȥ˴ؤơŬѲǽޤơʤݾڤԤ
#  ʤޤܥեȥѤˤľŪޤϴŪ
#  ʤ»˴ؤƤ⡤Ǥʤ
# 
#  @(#) $Id: genoffset,v 1.7 2001/11/15 04:12:47 hiro Exp $
# 

#
#  ӥåȥ
#
sub search_bit {
	my($val) = @_;
	my($val_bit);

	return(-1) if ($val == 0);

	$val_bit = 0;
	while (($val & 1) == 0) {
		$val >>= 1;
		$val_bit++;
	}
	return($val_bit);
}

#
#  եåͤν
#
sub parse_begin {
	while ($line = <>) {
		chop $line;

		return if ($line =~ /! END/);
		if ($line =~ /^([^ \t]+) = [#\$]?([^ \t]+)/) {
			printf "#define %s\t%d\n",$1,$2;
		}
	}
}

#
#  Ǥǥ쥯ƥ֤Υơ֥
#
%directives = (
	"long", "",
	"word", "",
	"int", "",
	"short", "",
	"byte", "",
	"zero", -1,
	"globl", 0,
	"global", 0,
	"align", 0,
	"data", 0,
	"stabs", 0,
	"type", 0,
	"size", 0,
);

#
#  ӥåȰ֤ν
#
sub parse_bit {
	my($endian, $size) = @_;
	my($offset, $dir, $val, $val_bit);

	$offset = 0;
	while ($line = <>) {
		chop $line;

		next if ($line =~ /^[ \t]*(\#.*)$/);
		return if ($line =~ /! END/);

		if ($line =~ /^([^ \t]+):/) {
			$label = $1;
		}
		elsif ($line =~ /[ \t]*\.([a-zA-Z]+)[ \t]*([^ \t]*)$/
				&& defined($dir = $directives{$1})) {
			$val = $2;

			# 16ʿ8ʿοͤؤѴ
			if ($val =~ /^0x(.+)$/) {
				$val = hex($1);
			}
			elsif ($val =~ /^0(.+)$/) {
				$val = oct($1);
			}

			if ($dir eq "") {
				# Τʤǥ쥯ƥ
				print STDERR "genoffset: unknown directive: ",
						"$line\n";
				$error = 1;
			}
			elsif ($dir == 0) {
				# ɤФ٤ǥ쥯ƥ
				next;
			}
			elsif ($dir == -1) {
				# .zero ǥ쥯ƥ֤ν
				$offset += $val;
				next;
			}
			elsif ($val == 0) {
				# ͤ 0 Υեɤν
				$offset += $dir;
				next;
			}

			# ӥåȰ֤õ
			$val_bit = do search_bit($val);

			# Хñ̤˴
			if ($endian eq "B") {
				$offset += $dir - 1;
				$offset -= $val_bit >> 3;
			}
			else {
				$offset += $val_bit >> 3;
			}
			$val_bit &= 0x07;

			# ñ̤˴
			if ($size eq "W") {
				if ($endian eq "B") {
					$val_bit += 24;
					$val_bit -= ($offset & 0x03) << 3;
				}
				else {
					$val_bit += ($offset & 0x03) << 3;
				}
				$offset &= ~0x03;
			}
			elsif ($size eq "H") {
				if ($endian eq "B") {
					$val_bit += 8;
					$val_bit -= ($offset & 0x01) << 3;
				}
				else {
					$val_bit += ($offset & 0x01) << 3;
				}
				$offset &= ~0x01;
			}
			last;
		}
		else {
			# ϤǤʤ
			print STDERR "genoffset: cannot parse: $line\n";
			$error = 1;
		}
	}

	# END ޤɤФ
	while ($line = <>) {
		chop $line;
		last if ($line =~ /! END/);
	}

	# ν
	$label =~ s/^_//;
	printf "#define %s\t%d\n",$label,$offset;
	printf "#define %s_bit\t%d\n",$label,$val_bit;
	printf "#define %s_mask\t0x%x\n",$label,(1 << $val_bit);
}

#
#  ǥ쥯ƥ֤ɤ߼
#
sub ref_bit {
	my($size, $dir, $directive);

	while ($line = <>) {
		chop $line;

		next if ($line =~ /^[ \t]*(\#.*)$/);
		return if ($line =~ /! END/);

		if ($line =~ /^_?ref_([0-9]+):/) {
			$size = $1;
		}
		elsif ($line =~ /[ \t]*\.([a-zA-Z]+)[ \t]*([^ \t]*)$/
				&& defined($dir = $directives{$1})) {
			$directive = $1;
			if ($dir eq "") {
				# Ͽ٤ǥ쥯ƥ
				$directives{$directive} = $size;
			}
		}
		else {
			# ϤǤʤ
			print STDERR "genoffset: cannot parse: $line\n";
			$error = 1;
		}
	}
}

#
#  ᥤ롼
#
print "/* This file is generated by genoffset. */\n";
print "\n";

$error = 0;
while ($line = <>) {
	chop $line;

	if ($line =~ /! BEGIN/) {
		do parse_begin();
	}
	elsif ($line =~ /! BIT_REF/) {
		do ref_bit();
	}
	elsif ($line =~ /! BIT_([BL])([BHW])/) {
		do parse_bit($1, $2);
	}
}
exit($error);
