;-------------------------------------------------------------------------;
;                                  TIGA                                   ;
;        Copyright (c) 1988-1990  Texas Instruments Incorporated.         ;
;			   All Rights Reserved				  ;
;-------------------------------------------------------------------------;
;   TMS340 Graphics Library						  ;
;-------------------------------------------------------------------------;
;                                                                         ;
;  long get_rev()							  ;
;                                                                         ;
;  The getrev function is called by the library function set_config to	  ;
;  obtain the silicon revision number of the TMS34010 or TMS34020	  ;
;  processor. Both the TIGA and TMS340 Graphics Library versions of	  ;
;  getrev obtain the revision number by executing the assembly language   ;
;  instruction REV. The graphics library version of this file, however,   ;
;  differs from TIGA in that it also contains a default illegal opcode	  ;
;  interrupt service routine that is installed at the time the program is ;
;  loaded into GSP memory. The primary purpose of this ISR is to support  ;
;  the earliest versions of the TMS34010, which treat REV as an illegal   ;
;  opcode. If your graphics card contains a TMS34020, or a later version  ;
;  of the TMS34010 that recognizes REV as a valid instruction, you are	  ;
;  welcome to delete the illegal opcode ISR from the getrev.asm file if   ;
;  you wish. (At the time of writing, one potential reason for removing   ;
;  the ISR is that not all TMS34010 and TMS34020 debuggers understand how ;
;  to deal intelligently with an ILLOP trap vector installed at load	  ;
;  time.) If you delete the ISR, you will also need to modify the lc.cmd  ;
;  link command file that resides in the \demos directory. As shipped	  ;
;  with the library, lc.cmd is set up to install the ILLOP trap vector at ;
;  the time a library-based application is loaded into GSP memory. (Refer ;
;  to the SECTIONS directive at the end of lc.cmd.)			  ;
;-------------------------------------------------------------------------;
;  07/18/88  Original Version Written...........................Mike Asal ;
;  07/17/88  Added getrev function...........................Graham Short ;
;  11/25/88  Modified for TIGA compatibility.....................W.S. Egr ;
;  04/20/90  Modified for general portability...............J.R. Van Aken ;
;-------------------------------------------------------------------------;
;
        .title    'get revision'
        .file     'getrev.asm'
;
;
;   DEFINE GLOBALS
;
	.global   _getrev,ILLOP_PC_IN_A0
;
;-------------------------------------------------------------------------;
;   Entry point for _getrev function					  ;
;-------------------------------------------------------------------------;
_getrev:
	rev	  A8
	rets

;-------------------------------------------------------------------------;
;   Entry point for illegal opcode ISR					  ;
;-------------------------------------------------------------------------;
ILLOP_ISR:
	move	  A0,-*SP,1	      ;save temporary register
	move	  *SP(2*32),A0,1      ;get PC from stack
	move	  -*A0,A0,0	      ;get illegal opcode from *(PC-16)
	srl	  6,A0		      ;check if opcode is REV
	jrnz	  IS_ILLOP	      ;jump if illegal opcode
	jrc	  IS_REV	      ;jump if REV instruction
;
; Opcode is not a REV instruction.  Enter infinite loop.  But first load
; address of illegal opcode into A0 in case programmer is debugging code.
;
IS_ILLOP:
	move	  *SP(2*32),A0,1      ;get PC from stack (for debug)
	subk	  16,A0 	      ;back up PC to offending opcode
ILLOP_PC_IN_A0:
	jr	  ILLOP_PC_IN_A0      ;infinite loop

;
; We have confirmed that opcode is a REV instruction.  Load revision code
; of 8 into register designated in register field of REV opcode.
;
IS_REV:
	move	  *SP(2*32),A0,1      ;get PC from stack
	move	  -*A0,A0,0	      ;get illegal opcode from *(PC-16)
	sll	  5,A0		      ;convert register number to offset
	addi	  REV_TABLE-32*32,A0  ;
	jump	  A0		      ;

REV_TABLE:
	movk	  8,A0
	jr	  REV_A0  ;special case:  temp reg. = REV's Rd
	movk	  8,A1
	jr	  END_REV
	movk	  8,A2
	jr	  END_REV
	movk	  8,A3
	jr	  END_REV
	movk	  8,A4
	jr	  END_REV
	movk	  8,A5
	jr	  END_REV
	movk	  8,A6
	jr	  END_REV
	movk	  8,A7
	jr	  END_REV
	movk	  8,A8
	jr	  END_REV
	movk	  8,A9
	jr	  END_REV
	movk	  8,A10
	jr	  END_REV
	movk	  8,A11
	jr	  END_REV
	movk	  8,A12
	jr	  END_REV
	movk	  8,A13
	jr	  END_REV
	movk	  8,A14
	jr	  END_REV
	nop			      ;no emulation of REV SP
	jr	  END_REV
	movk	  8,B0
	jr	  END_REV
	movk	  8,B1
	jr	  END_REV
	movk	  8,B2
	jr	  END_REV
	movk	  8,B3
	jr	  END_REV
	movk	  8,B4
	jr	  END_REV
	movk	  8,B5
	jr	  END_REV
	movk	  8,B6
	jr	  END_REV
	movk	  8,B7
	jr	  END_REV
	movk	  8,B8
	jr	  END_REV
	movk	  8,B9
	jr	  END_REV
	movk	  8,B10
	jr	  END_REV
	movk	  8,B11
	jr	  END_REV
	movk	  8,B12
	jr	  END_REV
	movk	  8,B13
	jr	  END_REV
	movk	  8,B14
	jr	  END_REV
	nop			      ;no emulation of REV SP
	jr	  END_REV
; Jump here for all cases except one.
END_REV:
	move	  A0,*SP+,1	      ;restore temporary register
; Jump here for special case in which designated register is A0.
REV_A0:
	reti


;-------------------------------------------------------------------------;
;  Default ILLOP interrupt vector					  ;
;  This is assigned to a vector address in the link command file lc.cmd.  ;
;-------------------------------------------------------------------------;
	.sect	 "default_illop_vector"
	.long	 ILLOP_ISR

	.end

