#! /usr/bin/perl
#
#  TOPPERS/JSP Kernel
#      Toyohashi Open Platform for Embedded Real-Time Systems/
#      Just Standard Profile Kernel
# 
#  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
#                              Toyohashi Univ. of Technology, JAPAN
#  Copyright (C) 2004 by Embedded and Real-Time Systems Laboratory
#              Graduate School of Information Science, Nagoya Univ., JAPAN
#  Copyright (C) 2005-2007 by Industrial Technology Institute,
#                              Miyagi Prefectural Government, JAPAN
# 
#  L쌠҂́Cȉ (1)`(4) ̏CFree Software Foundation 
#  ɂČ\Ă GNU General Public License  Version 2 ɋL
#  qĂ𖞂ꍇɌC{\tgEFAi{\tgEFA
#  ς̂܂ށDȉjgpEEρEĔzziȉC
#  pƌĂԁj邱Ƃ𖳏ŋD
#  (1) {\tgEFA\[XR[ȟ`ŗpꍇɂ́CL̒
#      \C̗pщL̖ۏ؋K肪Ĉ܂܂̌`Ń\[
#      XR[hɊ܂܂Ă邱ƁD
#  (2) {\tgEFACCu`ȂǁC̃\tgEFAJɎg
#      pł`ōĔzzꍇɂ́CĔzzɔhLgip
#      ҃}jAȂǁjɁCL̒쌠\C̗pщL
#      ̖ۏ؋Kfڂ邱ƁD
#  (3) {\tgEFAC@ɑgݍނȂǁC̃\tgEFAJɎg
#      płȂ`ōĔzzꍇɂ́Ĉꂩ̏𖞂
#      ƁD
#    (a) ĔzzɔhLgip҃}jAȂǁjɁCL̒
#        쌠\C̗pщL̖ۏ؋Kfڂ邱ƁD
#    (b) Ĕzž`ԂCʂɒ߂@ɂāCTOPPERSvWFNg
#        񍐂邱ƁD
#  (4) {\tgEFA̗pɂ蒼ړI܂͊ԐړIɐ邢Ȃ鑹
#      QCL쌠҂TOPPERSvWFNgƐӂ邱ƁD
# 
#  {\tgEFÁCۏ؂Œ񋟂Ă̂łDL쌠҂
#  TOPPERSvWFNǵC{\tgEFAɊւāC̓Kp\
#  ܂߂āCȂۏ؂sȂD܂C{\tgEFA̗pɂ蒼
#  ړI܂͊ԐړIɐȂ鑹QɊւĂC̐ӔC𕉂ȂD
# 
#  @(#) $Id: genoffset,v 1.1 2008/06/17 00:04:58 suikan Exp $
# 

#
#  makeoffset.c̃AZuʂ\̓̃ItZbg߂
#@@lTXRpC H8Cp
#
#@@g
#@@@perl genoffset makeoffset.src
#


#
#  
#
$infile = $ARGV[0];

#
#  rbgT[`
#
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);
}

#
#  ItZbgl̏o
#
#@@Ώۃp^[̗F
#@@@@MOV.L       #22,ER0
#@@@@MOV.L       #H'00000010,ER0
#@@@@MOV.W       #4,R0
#@@@@MOV.W       #H'0010,R0
#@@@@MOV.B       #8,R0L
#@@@@MOV.B       #8:8,R0L
#@@@@MOV.B       #H'1A:8,R0L
#
sub parse_offset {
	my($label) = @_;
	my($offset);

	while ($line = <INFILE>) {
		chomp $line;
							# 10i4oCg̏ꍇ
		if ($line =~ /MOV\.L +#([\d]+)(:32)* *, *ER0/) {
			$offset = $1;
			
			# `̏o
			printf "%s:\t.DEFINE\t\"%s\"\n", $label, $offset;
			last;
		}
							# 10i2oCg̏ꍇ
		elsif ($line =~ /MOV\.W +#([\d]+)(:16)* *, *R0/) {
			$offset = $1;
			
			# `̏o
			printf "%s:\t.DEFINE\t\"%s\"\n", $label, $offset;
			last;
		}
							# 10i1oCg̏ꍇ
		elsif ($line =~ /MOV\.B +#([\d]+)(:8)* *, *R0L/) {
			$offset = $1;
			
			# `̏o
			printf "%s:\t.DEFINE\t\"%s\"\n", $label, $offset;
			last;
		}
							# 16i4oCg̏ꍇ
		elsif ($line =~ /MOV\.L +#H\'([0-9a-fA-F]+)(:32)* *, *ER0/) {
			$offset = $1;
			
			# `̏o
			printf "%s:\t.DEFINE\t\"H\'%s\"\n", $label, $offset;
			last;
		}
							# 16i2oCg̏ꍇ
		elsif ($line =~ /MOV\.W +#H\'([0-9a-fA-F]+)(:16)* *, *R0/) {
			$offset = $1;
			
			# `̏o
			printf "%s:\t.DEFINE\t\"H\'%s\"\n", $label, $offset;
			last;
		}
							# 16i1oCg̏ꍇ
		elsif ($line =~ /MOV\.B +#H\'([0-9a-fA-F]+)(:8)* *, *R0L/) {
			$offset = $1;
			
			# `̏o
			printf "%s:\t.DEFINE\t\"H\'%s\"\n", $label, $offset;
			last;
		}

		elsif ($line =~ /^ *RTS$/) {	# rts߂̏ꍇ
			print "#error Parse error: $label by genoffset script\n";
			close(INFILE);
			print STDERR "Error: parse error $label by genoffset script\n";
			exit(1);
		}
	}
}

#
#  rbgtB[h̉
#
sub parse_bit {
	my($label) = @_;
	my($data, $zero, $ptn, $len, $offset, $bit);
	$data = "";

	while ($line = <INFILE>) {
		chomp $line;
		if ($line =~ s/\.DATA\.[LW]//) {
			$line =~ s/[^0-9a-fA-F]//g;
			$data .= $line;
		} else {
			last;
		}
	}
	
	$data =~ /(0+)([^0])/;
	$zero = $1;
	$ptn = $2;
	
	$len = length($zero);
	$offset = int($len / 2);
	$bit = search_bit($ptn);
	if (($len % 2) eq 0) {
		$bit += 4;
	}

	# `̏o
	printf "%s:\t.DEFINE\t\"%s\"\n", $label, $offset;
	printf "%s_bit:\t.DEFINE\t\"%s\"\n", $label, $bit;
	printf "%s_mask:\t.DEFINE\t\"H\'%x\"\n", $label, (1 << $bit);
}


#
#  C[`
#
print "; This file is generated by genoffset.\n";
print "\n";

$error = 0;
open(INFILE, $infile) || die "Cannot open $infile";

while ($line = <INFILE>) {
	chomp $line;
	
	if ($line =~ /^_OFFSET_DEF_([^ \t]+):/) {
		do parse_offset($1);
	}
	elsif ($line =~ /^_BIT_FIELD_OFFSET_([^ \t]+):/) {
		do parse_bit($1);
	}
}

close(INFILE);
exit($error);
