Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) #!/usr/bin/perl -s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) # SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) # NCR 53c810 script assembler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) # Sponsored by 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #       iX Multiuser Multitasking Magazine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) # Copyright 1993, Drew Eckhardt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #      Visionary Computing 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #      (Unix and Linux consulting and custom programming)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #      drew@Colorado.EDU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #      +1 (303) 786-7975 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #   Support for 53c710 (via -ncr7x0_family switch) added by Richard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #   Hirst <richard@sleepie.demon.co.uk> - 15th March 1997
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) # TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) # 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) # Basically, I follow the NCR syntax documented in the NCR53c710 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) # Programmer's guide, with the new instructions, registers, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) # from the NCR53c810.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) # Differences between this assembler and NCR's are that 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) # 1.  PASS, REL (data, JUMPs work fine), and the option to start a new 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #	script,  are unimplemented, since I didn't use them in my scripts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) # 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) # 2.  I also emit a script_u.h file, which will undefine all of 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) # 	the A_*, E_*, etc. symbols defined in the script.  This 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #	makes including multiple scripts in one program easier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) # 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) # 3.  This is a single pass assembler, which only emits 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #	.h files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) # XXX - set these with command line options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) $debug = 0;		# Print general debugging messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) $debug_external = 0;	# Print external/forward reference messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) $list_in_array = 1;	# Emit original SCRIPTS assembler in comments in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 			# script.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #$prefix;		# (set by perl -s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)                         # define all arrays having this prefix so we 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 			# don't have name space collisions after 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 			# assembling this file in different ways for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			# different host adapters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) # Constants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) # Table of the SCSI phase encodings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) %scsi_phases = ( 			
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)     'DATA_OUT', 0x00_00_00_00, 'DATA_IN', 0x01_00_00_00, 'CMD', 0x02_00_00_00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)     'STATUS', 0x03_00_00_00, 'MSG_OUT', 0x06_00_00_00, 'MSG_IN', 0x07_00_00_00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) # XXX - replace references to the *_810 constants with general constants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) # assigned at compile time based on chip type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) # Table of operator encodings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) # XXX - NCR53c710 only implements 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) # 	move (nop) = 0x00_00_00_00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) #	or = 0x02_00_00_00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) # 	and = 0x04_00_00_00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) # 	add = 0x06_00_00_00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) if ($ncr7x0_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)   %operators = (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)     '|', 0x02_00_00_00, 'OR', 0x02_00_00_00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)     '&', 0x04_00_00_00, 'AND', 0x04_00_00_00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)     '+', 0x06_00_00_00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)   );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)   %operators = (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)     'SHL',  0x01_00_00_00, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)     '|', 0x02_00_00_00, 'OR', 0x02_00_00_00, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)     'XOR', 0x03_00_00_00, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)     '&', 0x04_00_00_00, 'AND', 0x04_00_00_00, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)     'SHR', 0x05_00_00_00, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)     # Note : low bit of the operator bit should be set for add with 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)     # carry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)     '+', 0x06_00_00_00 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)   );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) # Table of register addresses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) if ($ncr7x0_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)   %registers = (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)     'SCNTL0', 0, 'SCNTL1', 1, 'SDID', 2, 'SIEN', 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)     'SCID', 4, 'SXFER', 5, 'SODL', 6, 'SOCL', 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)     'SFBR', 8, 'SIDL', 9, 'SBDL', 10, 'SBCL', 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)     'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)     'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)     'CTEST0', 20, 'CTEST1', 21, 'CTEST2', 22, 'CTEST3', 23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)     'CTEST4', 24, 'CTEST5', 25, 'CTEST6', 26, 'CTEST7', 27,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)     'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)     'DFIFO', 32, 'ISTAT', 33, 'CTEST8', 34, 'LCRC', 35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)     'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)     'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)     'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)     'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)     'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)     'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)     'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)   );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)   %registers = (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)     'SCNTL0', 0, 'SCNTL1', 1, 'SCNTL2', 2, 'SCNTL3', 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)     'SCID', 4, 'SXFER', 5, 'SDID', 6, 'GPREG', 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)     'SFBR', 8, 'SOCL', 9, 'SSID', 10, 'SBCL', 11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)     'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)     'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)     'ISTAT', 20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)     'CTEST0', 24, 'CTEST1', 25, 'CTEST2', 26, 'CTEST3', 27,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)     'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)     'DFIFO', 32, 'CTEST4', 33, 'CTEST5', 34, 'CTEST6', 35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)     'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)     'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)     'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)     'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)     'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)     'SCRATCHA0', 52, 'SCRATCHA1', 53, 'SCRATCHA2', 54, 'SCRATCHA3', 55,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)     'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)     'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)     'SIEN0', 64, 'SIEN1', 65, 'SIST0', 66, 'SIST1', 67,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)     'SLPAR', 68, 	      'MACNTL', 70, 'GPCNTL', 71,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)     'STIME0', 72, 'STIME1', 73, 'RESPID', 74, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)     'STEST0', 76, 'STEST1', 77, 'STEST2', 78, 'STEST3', 79,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)     'SIDL', 80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)     'SODL', 84,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)     'SBDL', 88,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)     'SCRATCHB0', 92, 'SCRATCHB1', 93, 'SCRATCHB2', 94, 'SCRATCHB3', 95
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)   );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) # Parsing regular expressions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) $identifier = '[A-Za-z_][A-Za-z_0-9]*';		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) $decnum = '-?\\d+';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) $hexnum = '0[xX][0-9A-Fa-f]+';		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) $constant = "$hexnum|$decnum";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) # yucky - since we can't control grouping of # $constant, we need to 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) # expand out each alternative for $value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) $value = "$identifier|$identifier\\s*[+\-]\\s*$decnum|".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)     "$identifier\\s*[+-]\s*$hexnum|$constant";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) print STDERR "value regex = $value\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) $phase = join ('|', keys %scsi_phases);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) print STDERR "phase regex = $phase\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) $register = join ('|', keys %registers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) # yucky - since %operators includes meta-characters which must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) # be escaped, I can't use the join() trick I used for the register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) # regex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if ($ncr7x0_family) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)   $operator = '\||OR|AND|\&|\+';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)   $operator = '\||OR|AND|XOR|\&|\+';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) # Global variables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) %symbol_values = (%registers) ;		# Traditional symbol table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) %symbol_references = () ;		# Table of symbol references, where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 					# the index is the symbol name, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 					# and the contents a white space 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 					# delimited list of address,size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 					# tuples where size is in bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) @code = ();				# Array of 32 bit words for SIOP 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) @entry = ();				# Array of entry point names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) @label = ();				# Array of label names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) @absolute = ();				# Array of absolute names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) @relative = ();				# Array of relative names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) @external = ();				# Array of external names
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) $address = 0;				# Address of current instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) $lineno = 0;				# Line number we are parsing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) $output = 'script.h';			# Output file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) $outputu = 'scriptu.h';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) # &patch ($address, $offset, $length, $value) patches $code[$address]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) # 	so that the $length bytes at $offset have $value added to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) # 	them.  
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) @inverted_masks = (0x00_00_00_00, 0x00_00_00_ff, 0x00_00_ff_ff, 0x00_ff_ff_ff, 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)     0xff_ff_ff_ff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) sub patch {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)     local ($address, $offset, $length, $value) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)     if ($debug) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	print STDERR "Patching $address at offset $offset, length $length to $value\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	printf STDERR "Old code : %08x\n", $code[$address];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)      }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)     $mask = ($inverted_masks[$length] << ($offset * 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)    
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)     $code[$address] = ($code[$address] & ~$mask) | 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	(($code[$address] & $mask) + ($value << ($offset * 8)) & 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	$mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)     printf STDERR "New code : %08x\n", $code[$address] if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) # &parse_value($value, $word, $offset, $length) where $value is 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) # 	an identifier or constant, $word is the word offset relative to 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #	$address, $offset is the starting byte within that word, and 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #	$length is the length of the field in bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) # Side effects are that the bytes are combined into the @code array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #	relative to $address, and that the %symbol_references table is 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) # 	updated as appropriate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) sub parse_value {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)     local ($value, $word, $offset, $length) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)     local ($tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)     $symbol = '';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)     if ($value =~ /^REL\s*\(\s*($identifier)\s*\)\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	$relative = 'REL';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	$symbol = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	$value = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) print STDERR "Relative reference $symbol\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)     } elsif ($value =~ /^($identifier)\s*(.*)/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	$relative = 'ABS';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	$symbol = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	$value = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) print STDERR "Absolute reference $symbol\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)     } 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)     if ($symbol ne '') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) print STDERR "Referencing symbol $1, length = $length in $_\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)      	$tmp = ($address + $word) * 4 + $offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	if ($symbol_references{$symbol} ne undef) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	    $symbol_references{$symbol} = 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		"$symbol_references{$symbol} $relative,$tmp,$length";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	    if (!defined($symbol_values{$symbol})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) print STDERR "forward $1\n" if ($debug_external);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		$forward{$symbol} = "line $lineno : $_";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	    } 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	    $symbol_references{$symbol} = "$relative,$tmp,$length";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)     } 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)     $value = eval $value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)     &patch ($address + $word, $offset, $length, $value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) # &parse_conditional ($conditional) where $conditional is the conditional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) # clause from a transfer control instruction (RETURN, CALL, JUMP, INT).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) sub parse_conditional {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)     local ($conditional) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)     if ($conditional =~ /^\s*(IF|WHEN)\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	$if = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	$conditional = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if ($if =~ /WHEN/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	    $allow_atn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	    $code[$address] |= 0x00_01_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	    $allow_atn = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	    print STDERR "$0 : parsed WHEN\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	    $allow_atn = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	    print STDERR "$0 : parsed IF\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	    die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	expected IF or WHEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)     if ($conditional =~ /^NOT\s+(.*)$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	$not = 'NOT ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	$other = 'OR';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	$conditional = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	print STDERR "$0 : parsed NOT\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	$code[$address] |= 0x00_08_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	$not = '';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	$other = 'AND'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)     $need_data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)     if ($conditional =~ /^ATN\s*(.*)/i) {#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	WHEN conditional is incompatible with ATN 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) " if (!$allow_atn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	$code[$address] |= 0x00_02_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	$conditional = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	print STDERR "$0 : parsed ATN\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)     } elsif ($conditional =~ /^($phase)\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	$phase_index = "\U$1\E";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	$p = $scsi_phases{$phase_index};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	$code[$address] |= $p | 0x00_02_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	$conditional = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	print STDERR "$0 : parsed phase $phase_index\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	$other = '';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	$need_data = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) print STDERR "Parsing conjunction, expecting $other\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)     if ($conditional =~ /^(AND|OR)\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	$conjunction = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	$conditional = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	$need_data = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	    Illegal use of $1.  Valid uses are 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	    ".$not."<phase> $1 data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	    ".$not."ATN $1 data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) " if ($other eq '');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	Illegal use of $conjunction.  Valid syntaxes are 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 		NOT <phase>|ATN OR data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		<phase>|ATN AND data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) " if ($conjunction !~ /\s*$other\s*/i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	print STDERR "$0 : parsed $1\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)     if ($need_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) print STDERR "looking for data in $conditional\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	if ($conditional=~ /^($value)\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	    $code[$address] |= 0x00_04_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	    $conditional = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	    &parse_value($1, 0, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	    print STDERR "$0 : parsed data\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	expected <data>.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)     if ($conditional =~ /^\s*,\s*(.*)/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	$conditional = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	if ($conditional =~ /^AND\s\s*MASK\s\s*($value)\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	    &parse_value ($1, 0, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	    print STDERR "$0 parsed AND MASK $1\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	    die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	expected end of line, not \"$2\"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) " if ($2 ne '');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	    die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	expected \",AND MASK <data>\", not \"$2\"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)     } elsif ($conditional !~ /^\s*$/) { 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	die "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	expected end of line" . (($need_data) ? " or \"AND MASK <data>\"" : "") . "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	not \"$conditional\"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) # Parse command line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) $output = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) $outputu = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) # Main loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) while (<STDIN>) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)     $lineno = $lineno + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)     $list[$address] = $list[$address].$_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)     s/;.*$//;				# Strip comments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)     chop;				# Leave new line out of error messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) # Handle symbol definitions of the form label:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)     if (/^\s*($identifier)\s*:(.*)/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	if (!defined($symbol_values{$1})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	    $symbol_values{$1} = $address * 4;	# Address is an index into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	    delete $forward{$1};		# an array of longs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	    push (@label, $1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 	    $_ = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	    die "$0 : redefinition of symbol $1 in line $lineno : $_\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) # Handle symbol definitions of the form ABSOLUTE or RELATIVE identifier = 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) # value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)     if (/^\s*(ABSOLUTE|RELATIVE)\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	$is_absolute = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	$rest = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	foreach $rest (split (/\s*,\s*/, $rest)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	    if ($rest =~ /^($identifier)\s*=\s*($constant)\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	        local ($id, $cnst) = ($1, $2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		if ($symbol_values{$id} eq undef) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 		    $symbol_values{$id} = eval $cnst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 		    delete $forward{$id};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 		    if ($is_absolute =~ /ABSOLUTE/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 			push (@absolute , $id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 			push (@relative, $id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 		    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 		    die "$0 : redefinition of symbol $id in line $lineno : $_\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 	    expected <identifier> = <value>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)     } elsif (/^\s*EXTERNAL\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 	$externals = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 	foreach $external (split (/,/,$externals)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	    if ($external =~ /\s*($identifier)\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 		$external = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 		push (@external, $external);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 		delete $forward{$external};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 		if (defined($symbol_values{$external})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 			die "$0 : redefinition of symbol $1 in line $lineno : $_\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 		$symbol_values{$external} = $external;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) print STDERR "defined external $1 to $external\n" if ($debug_external);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 		die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	expected <identifier>, got $external
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) # Process ENTRY identifier declarations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)     } elsif (/^\s*ENTRY\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 	if ($1 =~ /^($identifier)\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 	    push (@entry, $1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	    die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 	expected ENTRY <identifier>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) # Process MOVE length, address, WITH|WHEN phase instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)     } elsif (/^\s*MOVE\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	$rest = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	if ($rest =~ /^FROM\s+($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	    $transfer_addr = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	    $with_when = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	    $scsi_phase = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) print STDERR "Parsing MOVE FROM $transfer_addr, $with_when $3\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	    $code[$address] = 0x18_00_00_00 | (($with_when =~ /WITH/i) ? 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 		0x00_00_00_00 : 0x08_00_00_00) | $scsi_phases{$scsi_phase};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	    &parse_value ($transfer_addr, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	    $address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	} elsif ($rest =~ /^($value)\s*,\s*(PTR\s+|)($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	    $transfer_len = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	    $ptr = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	    $transfer_addr = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	    $with_when = $4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	    $scsi_phase = $5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	    $code[$address] = (($with_when =~ /WITH/i) ? 0x00_00_00_00 : 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		0x08_00_00_00)  | (($ptr =~ /PTR/i) ? (1 << 29) : 0) | 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 		$scsi_phases{$scsi_phase};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 	    &parse_value ($transfer_len, 0, 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	    &parse_value ($transfer_addr, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	    $address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	} elsif ($rest =~ /^MEMORY\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	    $rest = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 	    $code[$address] = 0xc0_00_00_00; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	    if ($rest =~ /^($value)\s*,\s*($value)\s*,\s*($value)\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 		$count = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		$source = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 		$dest =  $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) print STDERR "Parsing MOVE MEMORY $count, $source, $dest\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		&parse_value ($count, 0, 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		&parse_value ($source, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		&parse_value ($dest, 2, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) printf STDERR "Move memory instruction = %08x,%08x,%08x\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		$code[$address], $code[$address+1], $code[$address +2] if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 		($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 		$address += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 		die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	expected <count>, <source>, <destination>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	} elsif ($1 =~ /^(.*)\s+(TO|SHL|SHR)\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) print STDERR "Parsing register to register move\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 	    $src = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	    $op = "\U$2\E";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 	    $rest = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	    $code[$address] = 0x40_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	    $force = ($op !~ /TO/i); 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) print STDERR "Forcing register source \n" if ($force && $debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 	    if (!$force && $src =~ 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		/^($register)\s+(-|$operator)\s+($value)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) print STDERR "register operand  data8 source\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		$src_reg = "\U$1\E";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 		$op = "\U$2\E";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 		if ($op ne '-') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 		    $data8 = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 		    die "- is not implemented yet.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	    } elsif ($src =~ /^($register)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) print STDERR "register source\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 		$src_reg = "\U$1\E";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 		# Encode register to register move as a register | 0 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 		# move to register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 		if (!$force) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 		    $op = '|';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 		$data8 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	    } elsif (!$force && $src =~ /^($value)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) print STDERR "data8 source\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 		$src_reg = undef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 		$op = 'NONE';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		$data8 = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 		if (!$force) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 		    die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	expected <register>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		<data8>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		<register> <operand> <data8>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		    die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	expected <register>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	    if ($rest =~ /^($register)\s*(.*)$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		$dst_reg = "\U$1\E";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		$rest = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 	    die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) "$0 : syntax error in $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	expected <register>, got $rest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	    if ($rest =~ /^WITH\s+CARRY\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 		$rest = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 		if ($op eq '+') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 		    $code[$address] |= 0x01_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 		    die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) "$0 : syntax error in $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 	WITH CARRY option is incompatible with the $op operator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	    if ($rest !~ /^\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) "$0 : syntax error in $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	Expected end of line, got $rest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	    print STDERR "source = $src_reg, data = $data8 , destination = $dst_reg\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 		if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	    # Note that Move data8 to reg is encoded as a read-modify-write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	    # instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	    if (($src_reg eq undef) || ($src_reg eq $dst_reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 		$code[$address] |= 0x38_00_00_00 | 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 		    ($registers{$dst_reg} << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	    } elsif ($dst_reg =~ /SFBR/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		$code[$address] |= 0x30_00_00_00 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		    ($registers{$src_reg} << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 	    } elsif ($src_reg =~ /SFBR/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		$code[$address] |= 0x28_00_00_00 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		    ($registers{$dst_reg} << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) "$0 : Illegal combination of registers in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	Either source and destination registers must be the same,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 	or either source or destination register must be SFBR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	    $code[$address] |= $operators{$op};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	    
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	    &parse_value ($data8, 0, 1, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	    $code[$address] |= $operators{$op};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	    $code[$address + 1] = 0x00_00_00_00;# Reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	    $address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 	    die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	expected (initiator) <length>, <address>, WHEN <phase>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 		 (target) <length>, <address>, WITH <phase>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 		 MEMORY <length>, <source>, <destination>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) 		 <expression> TO <register>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) # Process SELECT {ATN|} id, fail_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)     } elsif (/^\s*(SELECT|RESELECT)\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	$rest = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	if ($rest =~ /^(ATN|)\s*($value)\s*,\s*($identifier)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	    $atn = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	    $id = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	    $alt_addr = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	    $code[$address] = 0x40_00_00_00 | 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 		(($atn =~ /ATN/i) ? 0x01_00_00_00 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	    $code[$address + 1] = 0x00_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	    &parse_value($id, 0, 2, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	    &parse_value($alt_addr, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	    $address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	} elsif ($rest =~ /^(ATN|)\s*FROM\s+($value)\s*,\s*($identifier)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	    $atn = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 	    $addr = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	    $alt_addr = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	    $code[$address] = 0x42_00_00_00 | 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 		(($atn =~ /ATN/i) ? 0x01_00_00_00 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	    $code[$address + 1] = 0x00_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	    &parse_value($addr, 0, 0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	    &parse_value($alt_addr, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	    $address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)         } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	    die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	expected SELECT id, alternate_address or 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 		SELECT FROM address, alternate_address or 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 		RESELECT id, alternate_address or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 		RESELECT FROM address, alternate_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)     } elsif (/^\s*WAIT\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 	    $rest = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) print STDERR "Parsing WAIT $rest\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 	if ($rest =~ /^DISCONNECT\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	    $code[$address] = 0x48_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	    $code[$address + 1] = 0x00_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	    $address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	} elsif ($rest =~ /^(RESELECT|SELECT)\s+($identifier)\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 	    $alt_addr = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	    $code[$address] = 0x50_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 	    &parse_value ($alt_addr, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 	    $address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	    die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	expected (initiator) WAIT DISCONNECT or 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		 (initiator) WAIT RESELECT alternate_address or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		 (target) WAIT SELECT alternate_address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) # Handle SET and CLEAR instructions.  Note that we should also do something
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) # with this syntax to set target mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)     } elsif (/^\s*(SET|CLEAR)\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	$set = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	$list = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	$code[$address] = ($set =~ /SET/i) ?  0x58_00_00_00 : 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	    0x60_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 	foreach $arg (split (/\s+AND\s+/i,$list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 	    if ($arg =~ /ATN/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 		$code[$address] |= 0x00_00_00_08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 	    } elsif ($arg =~ /ACK/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 		$code[$address] |= 0x00_00_00_40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	    } elsif ($arg =~ /TARGET/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 		$code[$address] |= 0x00_00_02_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	    } elsif ($arg =~ /CARRY/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 		$code[$address] |= 0x00_00_04_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 		die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 	expected $set followed by a AND delimited list of one or 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	more strings from the list ACK, ATN, CARRY, TARGET.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 	$code[$address + 1] = 0x00_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) 	$address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)     } elsif (/^\s*(JUMP|CALL|INT)\s+(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 	$instruction = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	$rest = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 	if ($instruction =~ /JUMP/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 	    $code[$address] = 0x80_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	} elsif ($instruction =~ /CALL/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 	    $code[$address] = 0x88_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) 	    $code[$address] = 0x98_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) print STDERR "parsing JUMP, rest = $rest\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) # Relative jump. 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	if ($rest =~ /^(REL\s*\(\s*$identifier\s*\))\s*(.*)/i) { 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	    $addr = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	    $rest = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) print STDERR "parsing JUMP REL, addr = $addr, rest = $rest\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	    $code[$address]  |= 0x00_80_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 	    &parse_value($addr, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) # Absolute jump, requires no more gunk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	} elsif ($rest =~ /^($value)\s*(.*)/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	    $addr = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	    $rest = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 	    &parse_value($addr, 1, 0, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	    die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	expected <address> or REL (address)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	if ($rest =~ /^,\s*(.*)/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	    &parse_conditional($1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	} elsif ($rest =~ /^\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	    $code[$address] |= (1 << 19);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 	    die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	expected , <conditional> or end of line, got $1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 	$address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)     } elsif (/^\s*(RETURN|INTFLY)\s*(.*)/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	$instruction = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 	$conditional = $2; 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) print STDERR "Parsing $instruction\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 	$code[$address] = ($instruction =~ /RETURN/i) ? 0x90_00_00_00 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	    0x98_10_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 	if ($conditional =~ /^,\s*(.*)/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 	    $conditional = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 	    &parse_conditional ($conditional);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 	} elsif ($conditional !~ /^\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 	    die
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) "$0 : syntax error in line $lineno : $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 	expected , <conditional> 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 	    $code[$address] |= 0x00_08_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	$code[$address + 1] = 0x00_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	$address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)     } elsif (/^\s*DISCONNECT\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	$code[$address] = 0x48_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	$code[$address + 1] = 0x00_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	$address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) # I'm not sure that I should be including this extension, but 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) # what the hell?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)     } elsif (/^\s*NOP\s*$/i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	$code[$address] = 0x80_88_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 	$code[$address + 1] = 0x00_00_00_00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 	$address += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) # Ignore lines consisting entirely of white space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)     } elsif (/^\s*$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) "$0 : syntax error in line $lineno: $_
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	expected label:, ABSOLUTE, CLEAR, DISCONNECT, EXTERNAL, MOVE, RESELECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	    SELECT SET, or WAIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) ";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) # Fill in label references
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) @undefined = keys %forward;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if ($#undefined >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)     print STDERR "Undefined symbols : \n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)     foreach $undef (@undefined) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 	print STDERR "$undef in $forward{$undef}\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)     exit 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) @label_patches = ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) @external_patches = ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) @absolute = sort @absolute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) foreach $i (@absolute) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)     foreach $j (split (/\s+/,$symbol_references{$i})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	$j =~ /(REL|ABS),(.*),(.*)/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 	$type = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	$address = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	$length = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 	die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) "$0 : $symbol $i has invalid relative reference at address $address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)     size $length\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	if ($type eq 'REL');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 	    
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	&patch ($address / 4, $address % 4, $length, $symbol_values{$i});
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) foreach $external (@external) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) print STDERR "checking external $external \n" if ($debug_external);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)     if ($symbol_references{$external} ne undef) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	for $reference (split(/\s+/,$symbol_references{$external})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 	    $reference =~ /(REL|ABS),(.*),(.*)/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 	    $type = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	    $address = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	    $length = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 	    
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	    die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) "$0 : symbol $label is external, has invalid relative reference at $address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)     size $length\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 		if ($type eq 'REL');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	    die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) "$0 : symbol $label has invalid reference at $address, size $length\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 		if ((($address % 4) !=0) || ($length != 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	    $symbol = $symbol_values{$external};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	    $add = $code[$address / 4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 	    if ($add eq 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 		$code[$address / 4] = $symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 		$add = sprintf ("0x%08x", $add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 		$code[$address / 4] = "$symbol + $add";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) print STDERR "referenced external $external at $1\n" if ($debug_external);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) foreach $label (@label) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)     if ($symbol_references{$label} ne undef) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 	for $reference (split(/\s+/,$symbol_references{$label})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 	    $reference =~ /(REL|ABS),(.*),(.*)/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) 	    $type = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	    $address = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 	    $length = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 	    if ((($address % 4) !=0) || ($length != 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 		die "$0 : symbol $label has invalid reference at $1, size $2\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	    if ($type eq 'ABS') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 		$code[$address / 4] += $symbol_values{$label};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 		push (@label_patches, $address / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 	    } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) # 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) # - The address of the reference should be in the second and last word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) #	of an instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) # - Relative jumps, etc. are relative to the DSP of the _next_ instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) # So, we need to add four to the address of the reference, to get 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) # the address of the next instruction, when computing the reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)   
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) 		$tmp = $symbol_values{$label} - 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 		    ($address + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 		die 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) # Relative addressing is limited to 24 bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) "$0 : symbol $label is too far ($tmp) from $address to reference as 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)     relative/\n" if (($tmp >= 0x80_00_00) || ($tmp < -0x80_00_00));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 		$code[$address / 4] = $tmp & 0x00_ff_ff_ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) # Output SCRIPT[] array, one instruction per line.  Optionally 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) # print the original code too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) open (OUTPUT, ">$output") || die "$0 : can't open $output for writing\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) open (OUTPUTU, ">$outputu") || die "$0 : can't open $outputu for writing\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) ($_ = $0) =~ s:.*/::;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) print OUTPUT "/* DO NOT EDIT - Generated automatically by ".$_." */\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) print OUTPUT "static u32 ".$prefix."SCRIPT[] = {\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) $instructions = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) for ($i = 0; $i < $#code; ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)     if ($list_in_array) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) 	printf OUTPUT "/*\n$list[$i]\nat 0x%08x : */", $i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)     printf OUTPUT "\t0x%08x,", $code[$i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)     printf STDERR "Address $i = %x\n", $code[$i] if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)     if ($code[$i + 1] =~ /\s*($identifier)(.*)$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) 	push (@external_patches, $i+1, $1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) 	printf OUTPUT "0%s,", $2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 	printf OUTPUT "0x%08x,",$code[$i+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)     if (($code[$i] & 0xff_00_00_00) == 0xc0_00_00_00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 	if ($code[$i + 2] =~ /$identifier/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 	    push (@external_patches, $i+2, $code[$i+2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 	    printf OUTPUT "0,\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 	    printf OUTPUT "0x%08x,\n",$code[$i+2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 	$i += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 	printf OUTPUT "\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 	$i += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)     $instructions += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) print OUTPUT "};\n\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) foreach $i (@absolute) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)     printf OUTPUT "#define A_$i\t0x%08x\n", $symbol_values{$i};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)     if (defined($prefix) && $prefix ne '') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 	printf OUTPUT "#define A_".$i."_used ".$prefix."A_".$i."_used\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) 	printf OUTPUTU "#undef A_".$i."_used\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)     printf OUTPUTU "#undef A_$i\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)     printf OUTPUT "static u32 A_".$i."_used\[\] __attribute((unused)) = {\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) printf STDERR "$i is used $symbol_references{$i}\n" if ($debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)     foreach $j (split (/\s+/,$symbol_references{$i})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 	$j =~ /(ABS|REL),(.*),(.*)/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 	if ($1 eq 'ABS') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 	    $address = $2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 	    $length = $3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 	    printf OUTPUT "\t0x%08x,\n", $address / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)     printf OUTPUT "};\n\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) foreach $i (sort @entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)     printf OUTPUT "#define Ent_$i\t0x%08x\n", $symbol_values{$i};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)     printf OUTPUTU "#undef Ent_$i\n", $symbol_values{$i};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) # NCR assembler outputs label patches in the form of indices into 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) # the code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) printf OUTPUT "static u32 ".$prefix."LABELPATCHES[] __attribute((unused)) = {\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) for $patch (sort {$a <=> $b} @label_patches) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)     printf OUTPUT "\t0x%08x,\n", $patch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) printf OUTPUT "};\n\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) $num_external_patches = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) printf OUTPUT "static struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)     "} ".$prefix."EXTERNAL_PATCHES[] __attribute((unused)) = {\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) while ($ident = pop(@external_patches)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)     $off = pop(@external_patches);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)     printf OUTPUT "\t{0x%08x, &%s},\n", $off, $ident;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)     ++$num_external_patches;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) printf OUTPUT "};\n\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) printf OUTPUT "static u32 ".$prefix."INSTRUCTIONS __attribute((unused))\t= %d;\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)     $instructions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) printf OUTPUT "static u32 ".$prefix."PATCHES __attribute((unused))\t= %d;\n", 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)     $#label_patches+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) printf OUTPUT "static u32 ".$prefix."EXTERNAL_PATCHES_LEN __attribute((unused))\t= %d;\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)     $num_external_patches;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) close OUTPUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) close OUTPUTU;