; sparrowhawk.h -- standard SparrowHawk definitions and macros ; language: SMAL32 assembly language, intended as an include file ; author: Douglas W. Jones ; date: June 19, 2014 ; based on: July 15, 2014 revision of hawk.h ; ; example: at the head of a smal 32 source file, include this line: ; | ; | USE "sparrowhawk.h" ; | ; example: if strict confinement to the sparrowhawk subset is required: ; | ; | STRICTSPARROW = 1 ; | USE "sparrowhawk.h" ; | ; --------------------- ; definitions of register symbols 0 to 15 EXT qREGISTERq ; relocation base for registers, ; defined so that register symbols R0 = qREGISTERq+0 ; cannot be confused with small R1 = qREGISTERq+1 ; integers, thus tightening up the R2 = qREGISTERq+2 ; assembly-time type checking R3 = qREGISTERq+3 ; offered by this macro package R4 = qREGISTERq+4 R5 = qREGISTERq+5 R6 = qREGISTERq+6 R7 = qREGISTERq+7 R8 = qREGISTERq+8 R9 = qREGISTERq+9 RA = qREGISTERq+10 ; hex names RB = qREGISTERq+11 RC = qREGISTERq+12 RD = qREGISTERq+13 RE = qREGISTERq+14 RF = qREGISTERq+15 R10 = qREGISTERq+10 ; decimal names also R11 = qREGISTERq+11 R12 = qREGISTERq+12 R13 = qREGISTERq+13 R14 = qREGISTERq+14 R15 = qREGISTERq+15 ; --------------------- ; definitions of special CPU registers ; each distinct group of special registers has its own relocation ; base so that these symbols become illegal outside of contexts ; where that register group is used EXT qCPUq PSW = qCPUq+0 TPC = qCPUq+1 TMA = qCPUq+2 TSV = qCPUq+3 CYC = qCPUq+8 EXT qADJq BCD = qADJq+2 EX3 = qADJq+3 CMSB = qADJq+4 SSQ = qADJq+5 PLUS1 = qADJq+8 PLUS2 = qADJq+9 PLUS4 = qADJq+10 PLUS8 = qADJq+11 PLUS16 = qADJq+12 PLUS32 = qADJq+13 PLUS64 = qADJq+14 PLUS128 = qADJq+15 ; --------------------- ; service macros MACRO ALIGN =x IF x > 1 IF (x & 1) = 1 ERROR odd parameter to ALIGN ELSE ALIGN (x>>1) .=.+(ABS(.)&(x>>1)) ENDIF ENDIF ENDMAC ; --------------------- ; internal macros for common instruction formats MACRO qBOUNDq =x,=min,=max IF (x > max) ERROR x > max out of bounds ELSEIF (x < min) ERROR x < min out of bounds ENDIF ENDMAC MACRO qABSBOUNDq =x,=min,=max IF (TYP(x) = 0) qBOUNDq x,min,max ELSEIF (TYP(x) = TYP(qREGISTERq)) ERROR register not allowed ENDIF ENDMAC MACRO qNZCONSTq =x IF (x = 0) ERROR constant 0 not allowed ENDIF ENDMAC MACRO qNZREGq =x IF (x = R0) ERROR R0 not allowed ENDIF ENDMAC MACRO qBRANCHq =op,=const qCONSTq = const - (.+2) >> 1 qBOUNDq qCONSTq,-128,+127 IF qCONSTq = -1 ERROR branch to self discouraged ENDIF B (op >> 8) B (qCONSTq & #FF) ENDMAC MACRO qONE5REGq =op,=dst,=x B (op >> 8) ! (dst-qREGISTERq) B (op & #FF) ! (x & #F) ENDMAC MACRO qTWOREGq =op,=dst,=x B (op >> 8) ! (dst-qREGISTERq) B (op & #FF) ! (x-qREGISTERq) ENDMAC MACRO qSPECREGq =op,=dst,=x,=base B (op >> 8) ! (dst-qREGISTERq) B (op & #FF) ! (x-base) ENDMAC MACRO qTWO5REGq =op,=dst,=s1,=x qBOUNDq x,1,16 B (op >> 8) ! (dst-qREGISTERq) B (s1-qREGISTERq << 4) ! (x & #F) ENDMAC MACRO qTHREEREGq =op,=dst,=s1,=s2 B (op >> 8) ! (dst-qREGISTERq) B (s1-qREGISTERq << 4) ! (s2-qREGISTERq) ENDMAC ; --------------------- ; macros for all HAWK opcodes MACRO MOVE =dst,=x qNZREGq dst qTWOREGq #F0F0,dst,x ENDMAC MACRO MOVECC =dst,=x qTWOREGq #F0E0,dst,x ENDMAC MACRO LOADS =dst,=x qNZREGq dst qTWOREGq #F0D0,dst,x ENDMAC MACRO LOADSCC =dst,=x qTWOREGq #F0C0,dst,x ENDMAC MACRO JSRS =dst,=x qTWOREGq #F0B0,dst,x ENDMAC MACRO STORES =dst,=x qNZREGq x qTWOREGq #F0A0,dst,x ENDMAC MACRO LOADL =dst,=x qNZREGq x qTWOREGq #F090,dst,x ENDMAC MACRO STOREC =dst,=x qNZREGq x qTWOREGq #F080,dst,x ENDMAC ; all long-format opcodes are gone! MACRO LIS =dst,=const qNZREGq dst qABSBOUNDq const,-#80,#7F B #D0 ! (dst-qREGISTERq) B const ENDMAC MACRO ORIS =dst,=const qNZREGq dst qABSBOUNDq const,#00,#FF B #C0 ! (dst-qREGISTERq) B const ENDMAC MACRO MOVESL =dst,=s1,=s2 qNZREGq s1 qTWO5REGq #B000,dst,s1,s2 ENDMAC MACRO ADDSL =dst,=s1,=s2 qNZREGq dst qTWO5REGq #A000,dst,s1,s2 ENDMAC MACRO ADDSR =dst,=s1,=s2 qTWO5REGq #9000,dst,s1,s2 ENDMAC MACRO ADDSRU =dst,=s1,=s2 qTWO5REGq #8000,dst,s1,s2 ENDMAC MACRO STUFFB =dst,=s1,=s2 qNZREGq dst qTHREEREGq #7000,dst,s1,s2 ENDMAC MACRO STUFFH =dst,=s1,=s2 qNZREGq dst qTHREEREGq #6000,dst,s1,s2 ENDMAC MACRO EXTB =dst,=s1,=s2 qNZREGq s1 qTHREEREGq #5000,dst,s1,s2 ENDMAC MACRO EXTH =dst,=s1,=s2 qNZREGq s1 qTHREEREGq #4000,dst,s1,s2 ENDMAC MACRO ADD =dst,=s1,=s2 qNZREGq s1 qNZREGq s2 qTHREEREGq #3000,dst,s1,s2 ENDMAC MACRO SUB =dst,=s1,=s2 qNZREGq s2 qTHREEREGq #2000,dst,s1,s2 ENDMAC MACRO TRUNC =dst,=src qNZREGq dst qBOUNDq src,1,16 qONE5REGq #10F0,dst,src ENDMAC MACRO SXT =dst,=src qNZREGq dst qBOUNDq src,1,16 qONE5REGq #10E0,dst,src ENDMAC MACRO BTRUNC =dst,=src qNZREGq dst qBOUNDq src,1,16 qONE5REGq #10D0,dst,src ENDMAC MACRO ADDSI =dst,=src qNZREGq dst qNZCONSTq src qBOUNDq src,-8,+8 IF src = +8 qONE5REGq #10C0,dst,0 ELSE qONE5REGq #10C0,dst,src ENDIF ENDMAC MACRO AND =dst,=src qNZREGq src qNZREGq dst qTWOREGq #10B0,dst,src ENDMAC MACRO OR =dst,=src qNZREGq src qNZREGq dst qTWOREGq #10A0,dst,src ENDMAC MACRO EQU =dst,=src qNZREGq dst qTWOREGq #1090,dst,src ENDMAC MACRO ADDC =dst,=src qTWOREGq #1070,dst,src ENDMAC MACRO SUBB =dst,=src qTWOREGq #1060,dst,src ENDMAC MACRO ADJUST =dst,=src qNZREGq dst qSPECREGq #1050,dst,src,qADJq ENDMAC MACRO PLUS =dst,=src qNZREGq dst qTWOREGq #1040,dst,src ENDMAC MACRO CPUGET =dst,=src qSPECREGq #1010,dst,src,qCPUq ENDMAC MACRO CPUSET =dst,=src qSPECREGq #1000,dst,src,qCPUq ENDMAC MACRO BGTU =const qBRANCHq #0F00,const ENDMAC MACRO BGT =const qBRANCHq #0E00,const ENDMAC MACRO BGE =const qBRANCHq #0D00,const ENDMAC MACRO BCR =const qBRANCHq #0C00,const ENDMAC MACRO BVR =const qBRANCHq #0B00,const ENDMAC MACRO BZR =const qBRANCHq #0A00,const ENDMAC MACRO BNR =const qBRANCHq #0900,const ENDMAC MACRO BLEU =const qBRANCHq #0700,const ENDMAC MACRO BLE =const qBRANCHq #0600,const ENDMAC MACRO BLT =const qBRANCHq #0500,const ENDMAC MACRO BCS =const qBRANCHq #0400,const ENDMAC MACRO BVS =const qBRANCHq #0300,const ENDMAC MACRO BZS =const qBRANCHq #0200,const ENDMAC MACRO BNS =const qBRANCHq #0100,const ENDMAC MACRO BR =const qBRANCHq #0000,const ENDMAC ; --------------------- ; macros for derived instructions MACRO TESTS =x LOADSCC R0,x ENDMAC MACRO TESTR =x MOVECC R0,x ENDMAC MACRO JUMPS =x JSRS R0,x ENDMAC MACRO CLR =x LIS x,0 ENDMAC MACRO BNE =x BZR x ENDMAC MACRO BLTU =x BCR x ENDMAC MACRO BEQ =x BZS x ENDMAC MACRO BGEU =x BCS x ENDMAC MACRO NOP =x BR .+2 ENDMAC MACRO SL =dst,=src ADDSL dst,R0,src ENDMAC MACRO SR =dst,=src ADDSR dst,R0,src ENDMAC MACRO SRU =dst,=src ADDSRU dst,R0,src ENDMAC MACRO BITTST =s1,=s2 IF s2<16 ADDSR R0,s1,s2+1 qBBSq = #0400 qBBRq = #0C00 ELSE IF s2<31 MOVESL R0,s1,(31-s2) ELSE MOVECC R0,s1 ENDIF qBBSq = #0100 qBBRq = #0900 ENDIF ENDMAC MACRO BBS =const qBRANCHq qBBSq,const ENDMAC MACRO BBR =const qBRANCHq qBBRq,const ENDMAC MACRO CMP =s1,=s2 SUB R0,s1,s2 ENDMAC MACRO NEG =dst,=src SUB dst,R0,src ENDMAC MACRO NOT =dst EQU dst,R0 ENDMAC MACRO ROL =dst ADDC dst,dst ENDMAC MACRO RTT =dst CPUGET R0,TPC ENDMAC IF ~DEF( STRICTSPARROW ) ; --------------------- ; macros for constant pool needed for relocatable LIL MACRO CONSTPOOL ALIGN 4 qCONSTPOOLq=. ENDMAC ; --------------------- ; macros for long Hawk instructions MACRO qEACOMPq =x,=const IF LEN(const)>0 LIS R1,const >> 8 ORIS R1,const & #FF PLUS R1,x ELSE qPCRELq = x-(.+6) LIS R1,qPCRELq >> 8 ORIS R1,qPCRELq & #FF PLUS R1,R0 ENDIF ENDMAC MACRO LEA =dst,=x,=const qEACOMPq x,const MOVE dst,R1 ENDMAC MACRO LEACC =dst,=x,=const qEACOMPq x,const MOVECC dst,R1 ENDMAC MACRO LOAD =dst,=x,=const qEACOMPq x,const LOADS dst,R1 ENDMAC MACRO LOADCC =dst,=x,=const qEACOMPq x,const LOADSCC dst,R1 ENDMAC MACRO JSR =dst,=x,=const qEACOMPq x,const JSRS dst,R1 ENDMAC MACRO STORE =dst,=x,=const qEACOMPq x,const STORES dst,R1 ENDMAC MACRO LIL =dst,=const IF TYP(const)=0 IF (const > 32767) ! (const < -32768) LIS dst, (const >> 16) ORIS dst, (const >> 8) & #FF ORIS dst, (const ) & #FF ELSEIF (const > 127) ! (const < -128) LIS dst, (const > 8) ORIS dst, (const ) & #FF ELSE LIS dst, const ENDIF ELSE LOAD dst,qCONSTPOOLq qLCSAVEq=. .=qCONSTPOOLq W const qCONSTPOOLq=. .=qLCSAVEq ENDIF ENDMAC ; --------------------- ; macros for derived long hawk instructions MACRO TEST =x,=disp LOADCC R0,x,disp ENDMAC MACRO ADDI =dst,=src,=const LEACC dst,src,const ENDMAC MACRO CMPI =x,=disp LEACC R0,x,-disp ENDMAC MACRO JUMP =x,=disp IF LEN(disp)>0 JSR R0,x,disp ELSE JSR R0,x ENDIF ENDMAC MACRO LIW =dst, =const LIL dst, const >> 8 ORIS dst, const & #FF ENDMAC ENDIF