nam Kermit68K ttl Utility subroutines module * Kermit68K: source file K68UTF * * Author: Roberto Bagnara (Bagnara@Iboinfn.Bitnet), * Bologna University, Physics Department, July 1987. * * All rights reserved to Bologna University, Italy. * * Permission is granted to any individual or institution * to use, copy, or redistribute this software so long as * it is not sold for profit, provided this copyright * notice is retained. * * Modification History: * * Version Date Who Comments * * 1.0.00 870701 Roberto Bagnara First official release use DefsFile Edition equ 0 psect K68UtilitySubs,0,0,Edition,0,0 ********************************* CopyStr *****************************ok * * * Null terminated strings copy subroutine. * * * * Entry conditions : D0.W target string maximum length * * A0.L pointer to target string * * A1.L pointer to source string * * * * Exit conditions : A0.L pointer to target string * * A1.L pointer to source string * * * *********************************************************************** CopyStr: TST.W D0 Null strings ? BEQ.S CopyStr4 Yes, do nothing MOVEM.L A0-A1,-(A7) Save pointers CopyStr1 SUBQ.W #1,D0 Decrement counter BNE.S CopyStr2 Continue copy, if there is room MOVE.B D0,(A0) End of target string, write terminator BRA.S CopyStr3 Restore pointers and return CopyStr2 MOVE.B (A1)+,(A0)+ Copy a character BNE.S CopyStr1 Repeat until end of source string CopyStr3 MOVEM.L (A7)+,A0-A1 Restore pointers CopyStr4 RTS ********************************* CompStr *****************************ok * * * Null terminated strings compare subroutine. * * * * Entry conditions : A0.L pointer to string 1 * * A1.L pointer to string 2 * * * * Exit conditions : D0.B completion code * * A0.L pointer to string 1 * * A1.L pointer to string 2 * * * *********************************************************************** CompStr: MOVEM.L A0-A1,-(A7) Save pointers CompStr1 MOVE.B (A0)+,D0 Get a character from string 1 CMP.B (A1)+,D0 Compare whit string 2 correspondent char BNE.S CompStr2 Compare failed, exit loop TST.B D0 Compare succeed, end of strings ? BNE.S CompStr1 No, stay in loop CompStr2 SEQ D0 Set completion code accordingly MOVEM.L (A7)+,A0-A1 Restore pointers RTS ********************************* DoPrity *****************************ok * * * Add an appropriate parity bit to a character. * * * * Entry conditions : D0.B 7-bit character * * * * Exit conditions : D0.B character with parity bit added * * * *********************************************************************** DoPrity: MOVEM.L D1-D2,-(A7) Save working registers MOVE.B Parity(A6),D1 Some kind of parity enabled ? BEQ.S DoPrity5 No, return ANDI.B #$7F,D0 Clear bit 7 CMPI.B #'M',D1 Mark ? BNE.S DoPrity1 No ORI.B #$80,D0 Yes, set bit 7 BRA.S DoPrity5 Return DoPrity1 CMPI.B #'S',D1 Space ? BEQ.S DoPrity5 Yes, return, bit 7 already cleared CLR.B D2 Clear the ones counter CMPI.B #'O',D1 Odd ? BNE.S DoPrity2 No ADDQ.B #1,D2 Yes, the ones counter starts from 1 DoPrity2 MOVEQ #6,D1 Set up for bit addressing DoPrity3 BTST D1,D0 Bit setted ? BEQ.S DoPrity4 No, try the next ADDQ.B #1,D2 Yes, increment the counter DoPrity4 DBF D1,DoPrity3 Repeat for bits 6-0 LSL.B #7,D2 Position the parity bit OR.B D2,D0 Ok, that's all DoPrity5 MOVEM.L (A7)+,D1-D2 Restore working registers RTS ****************************** HndlPar ********************************ok * * * Handle 8-th bit accordingly to parity selected. * * * * Entry conditions : D0.B character to be processed * * * * Exit conditions : D0.B processed character * * * *********************************************************************** HndlPar: TST.B Parity(A6) Parity selected ? BEQ.S HndlPar1 No, do nothing ANDI.B #$7F,D0 Yes, mask parity bit HndlPar1 RTS ********************************* UDiv ********************************ok * * * 32-bit/16-bit unsigned division. * * * * Entry conditions : D2.L dividend * * D3.W divisor * * * * Exit conditions : D0.L quotient * * D1.L remainder * * * *********************************************************************** UDiv: MOVE.L D2,D0 Get Dividend CLR.W D0 Clear lower part SWAP D0 Upper Dividend DIVU D3,D0 Divide MOVE.W D0,-(A7) Save upper quotient MOVE.W D2,D0 Remainder and lower Dividend DIVU D3,D0 Divide SWAP D0 CLR.L D1 MOVE.W D0,D1 Final remainder MOVE.W (A7)+,D0 Lower and upper quotients SWAP D0 Final quotient RTS Return ******************************* IntToAs *******************************ok * * * Integer to ASCII string conversion routine. * * * * Entry conditions : A0.L pointer to string buffer end * * D0.L number to convert * * D1.B flag for signed or unsigned number * * D2.L field length * * D3.L number base * * * * Exit conditions : A0.L pointer to string buffer start * * * *********************************************************************** IntToAs: MOVEM.W D4-D6,-(A7) Save working registers MOVE.B D1,D4 Load our flag for negative numbers BEQ.S IntToAs1 Unsigned number processing wanted TST.L D0 Signed, negative number ? SLT D4 Set our flag accordingly BGE.S IntToAs1 If positive number then continue NEG.L D0 Else negate it IntToAs1 MOVE.B D2,D5 Save field length CLR.B -(A0) Mark the end of string CLR.B D6 Clear the character counter IntToAs2 MOVE.L D0,D2 Dividend BSR UDiv Divide number by base (in D3) CMPI.B #9,D1 Convert remainder to ascii BGT.S IntToAs3 ADDI.B #$30,D1 BRA.S IntToAs4 IntToAs3 ADDI.B #$37,D1 IntToAs4 MOVE.B D1,-(A0) Store the obtained character ADDQ.B #1,D6 Increment the character counter TST.L D0 End of conversion ? BNE.S IntToAs2 No, repeat TST.B D4 Yes, was a negative number ? BEQ.S IntToAs5 No, continue MOVE.B #'-',-(A0) Yes, insert the minus sign ADDQ.B #1,D6 Increment the character counter IntToAs5 CMP.B D6,D5 Field full ? BLE.S IntToAs6 Yes MOVE.B #' ',-(A0) No, write a leading blank ADDQ.B #1,D6 Increment the character counter BRA.S IntToAs5 Continue padding until the field is full IntToAs6 MOVEM.W (A7)+,D4-D6 Restore working registers RTS ******************************* UppCase *******************************ok * * * Make a character upper-cased. * * * * Entry conditions : D3.B character to be converted * * * * Exit conditions : D3.B converted character * * * *********************************************************************** UppCase: CMPI.B #'a',D3 Below a ? BCS.S UppCase1 Yes, return CMPI.B #'z',D3 Above z ? BHI.S UppCase1 Yes, return SUBI.B #32,D3 No, make the character upper-cased UppCase1 RTS ******************************* IndxJump ******************************ok * * * Indexed jump, extract an address from a relative addresses table * * and jump to it. * * * * Entry conditions : D0.B index to jump table * * A1.L jump table start address * * * * Exit conditions : none, don't return * * * *********************************************************************** IndxJump: ANDI.W #$FF,D0 Make sure upper byte is cleared LSL.W #1,D0 Scale factor of 2 MOVE.W (A1,D0.W),D0 Load relative pointer JMP (A1,D0.W) Jump to service subroutine MacFind: BSR UppCasS Make the macro name upper-cased LEA MacroTbl(A6),A1 Load start address of macro table CMPA.L MTNxtChF(A6),A1 The macro table is empty ? BEQ.S MacFind2 Yes, return a bad completion code MacFind1 BSR CompStr Compare the two names TST.B D0 The two names are equal ? BNE.S MacFind3 Yes, return the macro address BSR MacSkip No, skip to next macro name TST.B D0 It was the last macro ? BEQ.S MacFind1 No, so check this one MacFind2 MOVEA.L A1,A0 Yes, this points to table end SF D0 Return a bad completion code RTS MacFind3 MOVEA.L A1,A0 This is the desired macro address ST D0 Return a positive completion code RTS MacSkip: TST.B (A1)+ Find the end of the macro name BNE.S MacSkip Loop until end of macro name found MacSkip1 TST.B (A1)+ Find the end of the macro body BNE.S MacSkip1 Loop until end of macro body found CMPA.L MTNxtChF(A6),A1 End of macro table ? SEQ D0 Set the completion code accordingly RTS UppCasS MOVE.L A0,-(A7) UppCasS1 MOVE.B (A0),D3 BEQ.S UppCasS2 BSR UppCase MOVE.B D3,(A0)+ BRA.S UppCasS1 UppCasS2 MOVE.L (A7)+,A0 RTS ends END