#asm * C include file -- run-time support for Small-C * SmallC Cross Compiler Run-Time Support. * Target 68HC11. * L. Konneker Feb. 7, 1987 * Retarget for 6811 and different assembler. ****************************************************** * Run-time start off * * for MC68HC11 EVB board * * Initialize stack * For EVB, put stack in high user ram, HEX DFFF downward ldx #57343 hex DFFF txs * Some would clear all of memory, not necessary on EVB. * Clear certain things so that start conditions are always same. * This is defensive programming but may hide bugs. clra clrb jmp _main * note main must not return * Run time routines are not listed in assembler output. OPT nol ****************************************************** * Small C v1 comparison support * All are dyadic except for lneg. * Reg x used as a temp cceq: tsx cpd 2,x beq cctrue bra ccfals ccne: tsx cpd 2,x bne cctrue bra ccfals cclt: tsx cpd 2,x bgt cctrue bra ccfals ccle: tsx cpd 2,x bge cctrue bra ccfals ccgt: tsx cpd 2,x blt cctrue bra ccfals ccge: tsx cpd 2,x ble cctrue bra ccfals ccult: tsx cpd 2,x bhi cctrue bra ccfals ccule: tsx cpd 2,x bhs cctrue bra ccfals ccugt: tsx cpd 2,x blo cctrue bra ccfals ccuge: tsx cpd 2,x bls cctrue bra ccfals * boolean negate, with coercion to boolean cclneg: cpd #0 beq cclne1 ldd #0 rts cclne1: ldd #1 rts * coerce to boolean type ccbool: bsr cclneg bra cclneg ****************************************************** * true and false returns common to all compare operations cctrue: ldd #1 bra ccret to common return ccfals: clra clrb bra ccret to common return ****************************************************** * relic ??? _Xstktop: * Put stack pointer in reg D tsx xgdx rts ****************************************************** * boolean * inclusive or primary and calling environ stacktop ccior: tsx oraa 2,x orab 3,x bra ccret * exclusive or primary and calling environ stacktop ccxor: tsx get copy of stack ptr eora 2,x form result eorb 3,x bra ccret * and primary and calling environ stacktop ccand: tsx anda 2,x andb 3,x bra ccret ****************************************************** * misc * sign extend low byte primary into high byte primary ccsex: clra tstb bpl *+3 coma rts ****************************************************** * shift * entry : D contains shift count, stack + 2 is operand * exit : D contains shifted operand, stack is restored * * Uses y reg. * No checking for negative shift count. * First, move shift count from d to x and move operand * from stack to d. ccasr: xgdx tsy ldd 2,y ccasr1: cpx #0 ble ccret asra rorb dex bra ccasr1 * left ccasl: xgdx tsy ldd 2,y ccasl1: cpx #0 ble ccret aslb rola dex bra ccasl1 ****************************************************** * A return routine common to shift and bitwise logical operations * Move ret adr down the stack on top of operand * Assert that on entry to this routine, * the stack ptr is still as it was on entry to the routine that * jumped here. * Must preserve reg D since it has the result. * Uses reg y. ccret: pulx capture return address tsy set up y as stack top ptr stx ,y store ret adr on top of stack rts ****************************************************** * Two's complement negate the primary register ccneg: coma one's complement comb addd #1 plus one rts ****************************************************** * Mult 16 bit times 16 bit yielding 16 bit. * Overflow is possible, not checked. * Signed and unsigned, same entry point. * * entry : D contains one operand, * @ stackptr is return adr * @ stackptr + 2 is operand * exit : D contains 16 bit operand, * stackptr is entry stackptr + 4 ( stack is restored * to as it was before caller pushed operand.) * cctmpd equ 0 cctmpx equ 2 ccrslt equ 6 ccsmul: ccmul: * shuffle stack tsx ldx 2,x pshx x op pshb d op psha * stack is now * d op * x op * return address * word for result * do multiply tsx ldaa cctmpx+1,x lo d times lo x mul std ccrslt,x ldd cctmpd+1,x lo d times hi x mul addb ccrslt,x add hi byte of partial result stab ccrslt,x ldaa cctmpd,x hi d times lo x ldab cctmpx+1,x mul addb ccrslt,x add hi byte of partial result stab ccrslt,x * restore stack, get result in d pulx pulx puly ret adr pula result pulb pshy rts ****************************************************** * Divide 16 bit times 16 bit yielding 16 bit. * Underflow is possible, not checked. * Signed and unsigned, same entry point. * entry : D contains divisor, * @ stackptr is return adr * @ stackptr + 2 is dividend * exit : D contains 16 bit quotient, * remainder not returned. * stackptr is entry stackptr + 4 ( stack is restored * to as it was before caller pushed operand.) * ccsdiv * Not implemented yet. * What follows is 6809 code. * To Be Done: convert all labels to start with cc *| signed divide *| calling: (left / right) *| push left *| ldd right *| jsr sdiv *| result in d, arg popped. *| * left=6 * right=2 * sign=1 * count=0 * return=4 * CARRY=1 *.globl sdiv,div,ASSERTFAIL *.globl prabs *sdiv: leas -4(s) * std right(s) * bne nozero * swi2 * .byte ASSERTFAIL *nozero: jsr prabs *div: clr count(s) | prescale divisor * inc count(s) *mscl: inc count(s) * aslb * rola * bpl mscl * std right(s) * ldd left(s) * clr left(s) * clr left+1(s) *div1: subd right(s) | check subtract * bcc div2 * addd right(s) * andcc #~CARRY * bra div3 *div2: orcc #CARRY *div3: rol left+1(s) | roll in carry * rol left(s) * lsr right(s) * ror right+1(s) * dec count(s) * bne div1 * ldd left(s) * tst sign(s) | sign fiddle * beq nochg * nega * negb * sbca #0 *nochg: std right(s) | move return addr * ldd return(s) * std left(s) * ldd right(s) * leas 6(s) * rts * *| prabs. converts both args to unsigned, and *| remembers result sign as sign a eor sign b *| used only by divide support *| result d contains right, sign is non-zero *| if result (from divide) should be negative. *| *| *.globl prabs * left=8. * right=4. * sign=3. *prabs: clr sign(s) * ldd left(s) * bge tryr * nega * negb * sbca #0 * std left(s) * inc sign(s) *tryr: ldd right(s) * bge done * nega * negb * sbca #0 * dec sign(s) * std right(s) *done: rts * ****************************************************** * Signed modulo. 16 bit modulo 16 bit yielding 16 bit. * Underflow is possible, not checked. * entry : D contains divisor, * @ stackptr is return adr * @ stackptr + 2 is dividend * exit : D contains 16 bit remainder, * quotient not returned. * stackptr is entry stackptr + 4 ( stack is restored * to as it was before caller pushed operand.) * ccsmod * Not implemented yet. * What follows is 6809 code. * To Be Done: convert all labels to start with cc *| signed mod *| calling: (left / right) *| push left *| ldd right *| jsr smod *| result in d, arg popped. *| * left=6 * right=2 * sign=1 * count=0 * return=4 * CARRY=1 *.globl smod,mod,ASSERTFAIL *.globl mrabs *smod: leas -4(s) * std right(s) * bne nozero * swi2 * .byte ASSERTFAIL *nozero: jsr mrabs *mod: clr count(s) | prescale divisor * inc count(s) *mscl: inc count(s) * aslb * rola * bpl mscl * std right(s) * ldd left(s) * clr left(s) * clr left+1(s) *mod1: subd right(s) | check subtract * bcc mod2 * addd right(s) * andcc #~CARRY * bra mod3 *mod2: orcc #CARRY *mod3: rol left+1(s) | roll in carry * rol left(s) * lsr right(s) * ror right+1(s) * dec count(s) * bne mod1 * tst sign(s) | sign fiddle * beq nochg * nega * negb * sbca #0 *nochg: std right(s) | move return addr * ldd return(s) * std left(s) * ldd right(s) * leas 6(s) * rts *| mrabs. converts both args to unsigned, and *| remembers result sign as the sign of the left *| argument. (for signed modulo) *| result d contains right, sign is non-zero *| if result (from mod) should be negative. *| *| *.globl mrabs * left=8. * right=4. * sign=3. *mrabs: clr sign(s) * ldd left(s) * bge tryr * nega * negb * sbca #0 * std left(s) * inc sign(s) *tryr: ldd right(s) * bge done * nega * negb * sbca #0 * std right(s) *done: rts * ****************************************************** * Case statement support * Case table is of the form: * FDB char_value, label * FDB char_value, label * FDB label,0 * That is, it consist of word pairs. * The first word of a pair is the switch value. * The second word of a pair is the label to jump to. * The last pair is special -- the second word is zero * and the first word is the label for the default case, * if there is one, else it is the label on the code * following the switch. * Note that this form is different than that for v2 SmallC. * TBD document the calling parameters * entry : D contains switch value, * @ stackptr is address of jump table * exit : exit is a jump * stackptr is entry stackptr + 2 ( stack is restored * to as it was before caller pushed switch value.) * cccase * Not implemented yet. * v2 code is readily available but table format differs. * 6809 version was lost. ****************************************************** * Unknown use, relics ??? _etext * .bss _eend * .data *_brkend: .wval _eend _edata ****************************************************** OPT l #endasm