xVersion" 2007.6.8.1" module 18xxx2 #document 18xxx2 // // x4th Forth compiler and x4th target libraries // (C) COPYRIGHT 1999 .. 2007 Blue Hell / Jan Punter // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // For all listed email addresses : // // > 8) & 0xff ; // SetBsr endm // // // =============================================== // SetBSRDefault macro movlb 0x00 ; // Select the default rambank endm // // // =============================================== // AddressToFsr0 macro aRegister movlw (aRegister >> 0) & 0xff ; // AddressToFsr0 movwf fsr0l movlw (aRegister >> 8) & 0xff movwf fsr0h endm // // // =============================================== // AddressToFsr1 macro aRegister movlw (aRegister >> 0) & 0xff ; // AddressToFsr1 movwf fsr1l movlw (aRegister >> 8) & 0xff movwf fsr1h endm // // // =============================================== // AddressToFsr2 macro aRegister movlw (aRegister >> 0) & 0xff ; // AddressToFsr2 movwf fsr2l movlw (aRegister >> 8) & 0xff movwf fsr2h endm // // // =============================================== // Utility macro's // =============================================== // PushNextRomAddress macro local BeyondMe ; // PushNextRomAddress ( -- wRomAddr ) PushLit (BeyondMe >> 0) & 0xff ; // Push low byte PushLit (BeyondMe >> 8) & 0xff ; // Push high byte return BeyondMe: endm // // // =============================================== // incf16 macro freg incf freg, f ; // incf16 btfsc Status, C incf freg + 1, f endm // // // =============================================== // incf32 macro freg incf freg + 0, f ; // incf32 btfsc Status, C incf freg + 1, f btfsc Status, C incf freg + 2, f btfsc Status, C incf freg + 3, f endm // // // =============================================== // incf24 macro freg incf freg + 0, f ; // incf24 btfsc Status, C incf freg + 1, f btfsc Status, C incf freg + 2, f endm // // // =============================================== // decf16 macro freg decf freg + 0, f ; // decf16 btfss Status, C decf freg + 1, f endm // // // =============================================== // decf16sz macro freg decf freg + 0, f ; // decf16sz S if Zero - kills wreg btfss Status, C decf freg + 1, f movf freg + 0, w iorwf freg + 1, w btfss Status, Z ; // S/ result was zero endm // // // =============================================== // addl16 macro dst16, lit16 movlw (lit16 >> 0) & 0xff ; // addl16 addwf dst16, f movlw (lit16 >> 8) & 0xff addwfc dst16 + 1, f endm // // // =============================================== // shl16 macro reg16 bcf Status, C ; // shl16 rlcf reg16 + 0, f rlcf reg16 + 1, f endm // // // =============================================== // rrc16 macro reg16 ; // Same as shrc16 rrcf reg16 + 1, f ; // rrc16 rrcf reg16 , f endm // // // =============================================== // shlc16 macro reg16 rlcf reg16 , f ; // shlc16 rlcf reg16 + 1, f endm // // // =============================================== // shr16 macro reg16 bcf Status, c ; // shr16 rrcf reg16 + 1, f rrcf reg16 + 0, f endm // // // =============================================== // shrc16 macro reg16 ; // Same as rrc16 rrcf reg16 + 1, f ; // shrc16 rrcf reg16, f endm // // // =============================================== // xorl16 macro dst16, lit16 movlw (lit16 >> 0) & 0xff ; // xorl16 xorwf dst16, f movlw (lit16 >> 8) & 0xff xorwf dst16 + 1, f endm // // =============================================== // shlc32 macro reg32 rlcf reg32 , f ; // shlc32 rlcf reg32 + 1, f rlcf reg32 + 2, f rlcf reg32 + 3, f endm // // // =============================================== // xorf16 macro dst16, src16 movf src16 , w ; // xorf16 xorwf dst16 , f movf src + 1, w xorwf dst + 1, f endm // // // =============================================== // xorf16d macro src16_1, src16_2, dst16 movf src16_1 + 0, w ; // xorf16d xorwf src16_2 + 0, w movwf dst16 + 0 movf src16_1 + 1, w xorwf src16_2 + 1, w movwf dst16 + 1 endm // // // =============================================== // clrf16 macro reg16 clrf reg16 ; // clrf16 clrf reg16 + 1 endm // // // =============================================== // clrf32 macro reg32 clrf reg32 ; // clrf32 clrf reg32 + 1 clrf reg32 + 2 clrf reg32 + 3 endm // // // =============================================== // cpfslt16 macro reg16_1, reg16_2 ; // Skip the next instruction if N1 < N2 (unsigned) ; // or skip if N1 - N2 < 0 local CheckHiUnEq, N1SmallerN2, N1NotSmallerN2 movwf <@" Quotient"> ; // Save wreg movf reg16_1 + 1, w subwf reg16_2 + 1, w bnz CheckHiUnEq ; // B/ N1 + 1 <> N2 + 1, test hi bytes ; // N1 + 1 == N2 + 1, test low bytes movf reg16_2, w ; // N2 to w subwf reg16_1, w ; // calc N1 - N2 :: negative -> N1 - N2 < 0 -> N1 < N2 movff <@" Quotient">, WREG ; // Restore wreg || NOT affecting flags bc N1NotSmallerN2 ; // N1 < N2 bra N1SmallerN2 CheckHiUnEq ; // Hi bytes are not equal, test 'm movf reg16_2 + 1, w ; // N2 == reg16_2 + 1 subwf reg16_1 + 1, w ; // Sub N1:: negative -> N1 - N2 < 0 -> N1 < N2 movff <@" Quotient">, WREG ; // Restore wreg || NOT affecting flags bc N1NotSmallerN2 N1SmallerN2 bra N1NotSmallerN2 + 2 ; // Skip next N1NotSmallerN2 endm // // // =============================================== // cpfseq16 macro reg16_1, reg16_2 ; // Skip the next instruction if N1 = N2 local N1NotEqualN2 movf reg16_2 + 1, w subwf reg16_1 + 1, w bnz N1NotEqualN2 ; // Hi bytes not equal ; // N1 + 1 equals N2 + 1 movf reg16_2, w subwf reg16_1, w btfss Status, Z ; // S/ N1 = N2 :: so skip next instruction N1NotEqualN2 endm // // // =============================================== // // A delay utility, the argument should be in the range [6..860] // Delay is in microseconds. // // Must be tuned for processor speed ! // which it IS for project c\002\progger // Delay macro aMuSecs local _DlyLp if aMuSecs < 3 | aMuSecs > 307 error "Argument for delay (aMuSecs) : out of range [3..307]" endif movlw (1000 * (aMuSecs) / (3 * 408)) - 1 ; // 1 cycles movwf _Quotient ; // 1 cycles _DlyLp decfsz <@" Quotient">, f ; // 1 cycles total : ( n * 3 + 3) * 102 ns goto _DlyLp ; // 2 cycles ; // 1 cycles endm // // // =============================================== // jr_f macro reg ; // jr_f local table movlw (table >> 8) & 0xff ; // Setup pclath with table address high byte movwf pclath movlw table & 0xff ; // Table address low byte into wreg addwf reg, w ; // Add ofset for the first time to pclath_w register pair btfsc status, c incf pclath, f addwf reg, w ; // Add offset again (table entries are two bytes in size) btfsc status, c incf pclath, f movwf pcl ; // set new pc (dispatch) table endm // // End of AsmHelpers // ========================================= // // ; // ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; // ;;; Start of code area ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; // Boot loader stuff ; // Fill in start and interrupt vectors, interrupts just jump through to the ; // APPLICATION. Reset must check eeprom and decide whether to jump into the ; // APPLICATION or reprogram the flash from an image present in EEPROM. ; // ; // The EEPROM has been changed to a size of 64 KByte (it was 64 Kbit) so it can ; // hold a new software image. The EEPROM layout has been changed as well the ; // appliction data starts at an offset 0x400 so that the first KByte can be used ; // for the loader software. ; // ; // EEPROM layout : ; // ; // $0000 .. $00ff : Bootloader memory ; // ; // $0000 : byte : loader_state ; // ; // $00 - Loading flash image from host, not a valid image yet ; // $01 - Valid image in EEPROM, must program FLASH ; // $02 - Programmed mew image into flash must contact host ASAP ; // the APPLICATION should check this state and act on it ; // $ff - FLASH programmed, host contacted, normal operation. ; // ; // all other values - run image in flash (normal operation). ; // ; // the APPLICATION should check for these cases and correct the value to $ff ; // ; // ; // $0001 : byte : inverse value of loader_state (1's complement). ; // ; // when this byte is not equal to the 1's complement of ; // loader_state : run image in flash (normal operation). ; // ; // ; // $0002 : word : image_length ; // ; // valid incremental length when loader_State is $00. ; // valid total length when loader_state is $01 or $02 ; // ; // ; // $0004 : word : checksum ; // ; // CRC-16 over preceding bytes, startvalue 0 is used for the CRC ; // when the CRC is in error : run image in flash (normal operation). ; // ; // ; // $0006 .. $00ff : not used, can have any value. ; // ; // ; // $0100 .. $ffff : application storage or flash image ; // ; // Depends upon loader_state what is present : ; // ; // $00 - invalid image, partial FLASH image present ; // $01 - valid FLASH image with length image_length ; // $02 - valid FLASH image with length image_length ; // $ff - APPLICATION data ; // All other values, invalid checksum or invalid loader_state : ; // APPLICATON data, but possibly invalid. LoaderVersion equ 1 ; // Loaders version number ; // RAM layout during boot process EE_ADDR equ 0x000 ; // Two bytes EEProm address EE_DATA equ 0x002 ; // Two bytes EEProm data buffer EE_PTR equ 0x004 ; // Two bytes pointer in EEProm EE_ACK equ 0x006 ; // One byte ACK / NAK received after write FLASH_CNT equ 0x007 ; // Two bytes, nr of bytes to flash FLASH_PTR equ 0x009 ; // Two bytes pointer in FLASH COUNTER equ 0x00b ; // Two bytes counter BSTATE equ 0x00d ; // One byte loader_state CRC_16 equ 0x00e ; // Two bytes CRC ; // Physical vectors. org 0x0000 bra BootLoader ; // Jump into the bootloader ; // --------------------------------------------------------------------------- ; // CalcCrc16 : calculate CRC-16 checksum from CRC and value passed in wreg CalcCrc16 movwf tmp1 ; // Get bData into tmp1 movlw 8 ; // Handle 8 bits bra Crc16_goon ; // B/ into the 'real thing' org 0x0008 bra HighPriorityInterruptVector ; // Jump into the application interrupt handler ; // --------------------------------------------------------------------------- ; // SetupRegs : Setup registers to be able to access external eeprom ; // ; // Application dependent : must at least setup some physical IO ok SetupRegs movlw B'01001110' ; // Setup most port pins as digital I/O movwf ADCON1 ; // Initialize i2c port bsf I2C_LAT , <@" Pin_SCL"> ; // Set SCL high bcf I2C_TRIS, <@" Pin_SCL"> ; // Put SCL line in output state return ; // --------------------------------------------------------------------------- ; // LoaderGetVersion : returns the loader version into wreg LoaderGetVersion movlw LoaderVersion return org 0x0018 bra LowPriorityInterruptVector ; // Jump into the application interrupt handler ; // Helpers for boot loader ; // --------------------------------------------------------------------------- ; // CalcCrc16 : calculate CRC-16 checksum from CRC and value passed in wreg ; // Moved some code into 'vector gaps' Crc16_goon movwf tmp2 BLCC16_Loop movf tmp1, w ; // Data into wreg xorwf CRC_16, w ; // Xor with old crc -> wreg movwf tmp3 ; // Keep bit 0 in flag for later bcf Status, c ; // Clear carry, make a right SHIFT rrc16 CRC_16 rrcf tmp1, f ; // drop a bit of Data rrcf tmp3, f ; // rotate bit 0 of tmp3 into carry btfss Status, c ; // skip next if carry set bra BLCC16_WasZero ; // B/ carry was not set ; // Xor OldCrc with shifted polynomial xorl16 CRC_16, 0xa001 ; // This leaves the carry unchanged BLCC16_WasZero decfsz tmp2, f ; // djnz EC_COUNTER, EC_CC_Loop bra BLCC16_Loop return ; // --------------------------------------------------------------------------- ; // i2cTxByte : transmit wreg to the i2c device i2cTxByte movwf tmp1 ; // Store TxBuf movlw 8 ; // Init counter, 8 bits to do movwf tmp2 TXi2cLp bcf I2C_LAT, <@" Pin_SCL"> ; // Clock low bcf I2C_LAT, <@" Pin_SDA"> ; // Output bit 0 (0) btfsc tmp1, 7 bsf I2C_LAT, <@" Pin_SDA"> ; // Output bit 0 (1) bsf I2C_LAT, <@" Pin_SCL"> ; // Clock to high rlncf tmp1, f ; // Rotate TxBuf left (not through carry) decfsz tmp2, f ; // 8 bits done ? bra TXi2cLp ; // No. ; // Bit in, reads ACK / NAK bcf I2C_LAT , <@" Pin_SCL"> ; // Return SCL to low bcf I2C_LAT , <@" Pin_SDA"> ; // Make SDA low bsf I2C_TRIS, <@" Pin_SDA"> ; // Put SDA line in input state bsf I2C_LAT , <@" Pin_SCL"> ; // Clock high setf EE_ACK ; // Assume ACK btfsc I2C_PORT, <@" Pin_SDA"> ; // Read SDA pin / S/ on ack clrf EE_ACK ; // No ack bcf I2C_LAT , <@" Pin_SCL"> ; // Return SCL to low bcf I2C_TRIS, <@" Pin_SDA"> ; // Put SDA line in output state return ; // --------------------------------------------------------------------------- ; // i2cStart : transmit a bus start i2cStart bsf I2C_LAT, <@" Pin_SDA"> bsf I2C_LAT, <@" Pin_SCL"> ; // SDA goes low during SCL high i2cToggle nop nop btg I2C_LAT, <@" Pin_SDA"> return ; // --------------------------------------------------------------------------- ; // i2cStop : transmit a bus stop i2cStop bcf I2C_LAT, <@" Pin_SDA"> bsf I2C_LAT, <@" Pin_SCL"> ; // SDA goes high during SCL high bra i2cToggle ; // --------------------------------------------------------------------------- ; // i2cTxAddress : transmit the 16 bit address contained in EE_ADDR ; // preceded by START and DeviceAddress/Write i2cTxAddress rcall i2cStart movlw 0xa0 ; // Device address + write rcall i2cTxByte movf EE_ADDR + 1, w rcall i2cTxByte movf EE_ADDR + 0, w bra i2cTxByte ; // --------------------------------------------------------------------------- ; // i2cRxByte : read a byte from i2c into wreg i2cRxByte bsf I2C_TRIS, <@" Pin_SDA"> ; // Put SDA line in input state movlw 8 ; // 8 bits of data movwf tmp2 i2cRxLp rlncf tmp3, f ; // Shift data to buffer ; // Bit in bsf I2C_LAT, <@" Pin_SCL"> ; // Clock high bcf tmp3, 0 ; // Assume data bit is 0 btfsc I2C_PORT, <@" Pin_SDA"> ; // Read SDA pin bsf tmp3, 0 ; // Data bit is 1 instead bcf I2C_LAT, <@" Pin_SCL"> ; // Return SCL to low decfsz tmp2, f ; // 8 bits done ? bra i2cRxLp bsf I2C_LAT, <@" Pin_SDA"> ; // Send NAK bcf I2C_TRIS, <@" Pin_SDA"> ; // Put SDA line in output state bsf I2C_LAT, <@" Pin_SCL"> ; // Clock high movf tmp3, w ; // Data into wreg bcf I2C_LAT, <@" Pin_SCL"> ; // Return SCL to low return ; // --------------------------------------------------------------------------- ; // PreReadEEByte : read byte from EE_ADDR into wreg PreReadEEByte rcall i2cTxAddress ; // Send address prefix stuff rcall i2cStart ; // re-issue start movlw 0xa1 ; // Device address + read rcall i2cTxByte rcall i2cRxByte ; // Read byte into bra i2cStop ; // Issue bus STOP ; // --------------------------------------------------------------------------- ; // incEeAddr : Increment EE_ADDR ; // Keeps wreg intact incEeAddr incf16 EE_ADDR return ; // --------------------------------------------------------------------------- ; // ReadEEByte : read a byte from eeprom address EE_ADDR into EE_DATA and into wreg ; // increments EE_ADDR ReadEEByte rcall PreReadEEByte movwf EE_DATA + 0 ; // Store byte bra incEeAddr ; // Leaves wreg intact ; // --------------------------------------------------------------------------- ; // WriteEEByte : Write a byte from EE_DATA to eeprom address EE_ADDR ; // increments EE_ADDR WriteEEByte rcall i2cTxAddress ; // Send address prefix stuff movf EE_DATA, w WriteEEByteAgain rcall i2cTxByte ; // Write byte to bus rcall i2cStop ; // Issue bus STOP, starts programming ; // Wait for device to respond again after programming clrwdt ; // Give us some time WriteEEByteWait rcall i2cStart ; // Send bus start movlw 0xa0 ; // start write op rcall i2cTxByte ; // Check for ACK btfss EE_ACK, 0 ; // S/ Ack seen bra WriteEEByteWait ; // B/ no ack seen yet (dog might terminate this) rcall i2cStop ; // Terminate bus activity bra incEeAddr ; // Advance EE device address and return ; // --------------------------------------------------------------------------- ; // WriteEEWord : Write a word from EE_DATA to eeprom address EE_ADDR ; // increments EE_ADDR by two WriteEEWord rcall WriteEEByte rcall i2cTxAddress ; // Send address prefix stuff movf EE_DATA + 1, w bra WriteEEByteAgain ; // Advance EE device address and return ; // --------------------------------------------------------------------------- ; // @@@@ to be removed later for a real 18f452 ; // EEADR EQU H'0FA9' ; // EEDATA EQU H'0FA8' ; // EECON2 EQU H'0FA7' ; // EECON1 EQU H'0FA6' ; // EEPGD EQU H'0007' ; // CFGS EQU H'0006' ; // FREE EQU H'0004' ; // WRERR EQU H'0003' ; // WREN EQU H'0002' ; // WR EQU H'0001' ; // RD EQU H'0000' ; // END @@@@ to be removed later ; // --------------------------------------------------------------------------- ; // StartWrite - starts a write or erase operation StartWrite clrwdt movlw 0x55 movwf eecon2 movlw 0xaa movwf eecon2 bsf eecon1, wr nop return ; // --------------------------------------------------------------------------- ; // BootLoader - does it all BootLoader ; // Determine what to do based upon eeprom contents ; // ; // Either : ; // ; // - load new software from eeprom into flash ; // - jump into existing software ; // ICE BUG FIX ; movlw 0xb0 ; // To make table reads work correctly in MPLAB ICE 2000 movwf 0xf9c ; // Not needed in production code (but it doesn't harm) ; ; // ICE BUG FIX - END bcf intcon, gie ; // Disable all interrupts SetBSRDefault ; // Setup BSR register rcall SetupRegs ; // Initialize some registers bsf I2C_LAT , <@" Pin_SDA"> ; // Set SCL high bcf I2C_TRIS, <@" Pin_SDA"> ; // Put SCL line in output state ; // Check EEPROM clrf EE_ADDR + 0 ; // Set address pointer to zero clrf EE_ADDR + 1 clrf CRC_16 + 0 ; // Clear CRC clrf CRC_16 + 1 movlw 6 ; // Check six bytes movwf COUNTER BootCrcCheck rcall ReadEEByte ; // Read next byte into EE_DATA and into wreg rcall CalcCrc16 decfsz COUNTER bra BootCrcCheck movf CRC_16 + 0, w iorwf CRC_16 + 1, w bnz ResetVector ; // B/ CRC error, perform no load ; // CRC OK, read state clrf EE_ADDR ; // Read state rcall ReadEEByte ; // Read byte into EE_DATA and into wreg movwf BSTATE rcall ReadEEByte ; // Read control byte xorlw 0xff cpfseq BSTATE ; // S/ control byte OK bra ResetVector ; // B/ error in control byte, normal operation ; // CRC OK, control byte OK, check state ; // State 1 is the only state of interest to us, we must flash a new image then ; // bra ProgOk ; // Skip programming, comment out/in as needed movlw 0x01 ; // Check 0x01 cpfseq BSTATE ; // S/ state = 1 bra ResetVector ; // B/ state <> 1, not interested, normal operation BootLoaderDoIt ; // State = 1, valid FLASH image with length image_length ; // ; // Perform FLASH programming, copy EEPROM to FLASH movlw 0x02 ; // Read byte count movwf EE_ADDR rcall ReadEEByte ; // was : read eeword rcall PreReadEEByte movwf EE_DATA + 1 ; // Store byte movlw 61 ; // Add 61 to byte count to round up addwf EE_DATA + 0, f ; // should be 63, but use 61 to skip the CRC clrf wreg ; // The image builder must cooperate by making addwfc EE_DATA + 1, f ; // images a multiple of 64 bytes + 2 for the CRC movlw 6 ; // Divide byte count by 64, erase page count movwf COUNTER BL_DL shr16 EE_DATA ; // Shift right one bit decfsz COUNTER ; // S/ done bra BL_DL ; // B. not done yet movff EE_DATA + 0, FLASH_CNT + 0 ; // Store erase page count into FLASH_CNT movff EE_DATA + 1, FLASH_CNT + 1 clrf tblptru ; // Setup table latch movlw ( ResetVector >> 8) & 0xff movwf tblptrh movlw ( ResetVector >> 0) & 0xff movwf tblptrl movlw ( <@" AdminStart"> >> 0) & 0xff ; // Setup EEProm address movwf EE_ADDR + 0 movlw ( <@" AdminStart"> >> 8) & 0xff movwf EE_ADDR + 1 BL_loop_erase ; // Erase page bsf eecon1, eepgd ; // point to FLASH program memory bcf eecon1, cfgs ; // access FLAH program memory bsf eecon1, wren ; // enable FLASH writes bsf eecon1, free ; // Enable row erase rcall StartWrite ; // Unlock sequence, start erase, stall CPU tblrd *- ; // Dummy read movlw 8 ; // Setup erase page byte counter, 8 write pages in 1 erase page movwf COUNTER + 0 BL_loop_outer movlw 8 ; // Setup write page byte counter, 8 bytes in a write page movwf COUNTER + 1 BL_loop_inner rcall ReadEEByte ; // Read data byte into EE_DATA and into wreg movwf tablat ; // into tablat tblwt +* ; // Short data write to buffer decfsz COUNTER + 1 bra BL_loop_inner ; // Flash 8 bytes bsf eecon1, eepgd ; // Point to FLASH program memory bcf eecon1, cfgs ; // Access FLASH program memory bcf eecon1, free ; // Disable erase ops bsf eecon1, wren ; // Enable write to memory rcall StartWrite ; // Unlock sequence, start write, stall CPU ; // Write verification movlw 8 ; // Set EE_ADDR 8 location back movwf COUNTER + 1 ; // Setup read page byte counter, 8 bytes in a page subwf EE_ADDR movlw 0 subwfb EE_ADDR + 1 movlw 8 ; // Set TBLPTR 8 location back subwf TBLPTRL movlw 0 subwfb TBLPTRH BL_Loop_check rcall ReadEEByte ; // Read next EE byte into EE_DATA and into wreg tblrd +* ; // Read FLASH byte into TABLAT cpfseq tablat ; // S/ FLASH contents OK reset ; // B/ error detected, just reboot. decfsz COUNTER + 1 ; // S/ done verifying 8 bytes bra BL_Loop_check ; // B/ not done decfsz COUNTER + 0 ; // S/ all 8 write pages in erase page done bra BL_loop_outer ; // B/ more write pages in this erase page tblrd +* ; // Dummy read to set erase pointer OK movlw 1 ; // Decrement erase page counter subwf FLASH_CNT + 0 movlw 0 subwfb FLASH_CNT + 1 movf FLASH_CNT + 1, w iorwf FLASH_CNT + 0, w bnz BL_loop_erase ; // B/ more erase pages to do ; // All programming OK, proceed ProgOk ; // Label for debugging. bcf eecon1, wren ; // Disable FLASH writes clrf EE_ADDR + 0 ; // Set loader stater OK clrf EE_ADDR + 1 movlw 2 movwf EE_DATA xorlw 0xff movwf EE_DATA + 1 rcall WriteEEWord ; // Fix CRC clrf CRC_16 + 0 ; // Clear CRC clrf CRC_16 + 1 movlw 4 ; // Process 4 bytes movwf COUNTER clrf EE_ADDR ; // Start at 0 FixCrcLp rcall ReadEEByte ; // Read next byte into EE_DATA and into wreg rcall CalcCrc16 decfsz COUNTER bra FixCrcLp movff CRC_16 + 0, EE_DATA + 0 movff CRC_16 + 1, EE_DATA + 1 ; // The following two instructions are not needed, ReadEEByte will do it ; // ; // movlw 0x04 ; // movwf EE_ADDR rcall WriteEEWord Reset ; // Reboot the controller, let APLLICATION handle the rest. ; // End of boot loader ; // ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; // APPLICATION /////////////////////////////////////////////////////////////// org 0x0200 ; // RESET ResetVector bra ValueInit ; // Go initialize Value defined words. ; // !! a compiler generated entry point !! HighPriorityInterruptVector nop ; // No priority support, just fall through LowPriorityInterruptVector ; // Save processor status movwf WTMP ; // Copy W to WTMP register !! in ACCESS bank !! movff bsr , <@" BSRTmp"> ; // Save BSR SetBSRDefault ; // Clear BSR to default movff status, <@" StatusTmp"> ; // Save Status movff fsr0l , <@" FSRTmpL"> ; // Save fsr0l movff fsr0h , <@" FSRTmpH"> ; // Save fsr0h movff pclath, <@" PCHTmp"> ; // Save pclath goto <@" LowPriorityInterrupt"> HighPriorityInterruptReturn nop ; // No priority support, just fall through LowPriorityInterruptReturn ; // Restore processor status movff <@" PCHTmp"> , pclath ; // Restore pclath movff <@" FSRTmpH"> , fsr0h ; // Restore fsr0h movff <@" FSRTmpL"> , fsr0l ; // Restore fsr0l movff <@" BSRTmp"> , bsr ; // Restore bsr movf WTMP , w ; // Restore wreg movff <@" StatusTmp">, status ; // Restore status retfie ; // ;;;;;;;;;;;;;;;;;;;; End of startup code ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; // ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; endMacro // //////////////////////////////////////////////////////////////////////////// macro AsmConfig ( errorLevel LinesPerPage Radix ) ( -- ) ; // Set initial error level 0 == all eerors and warnings active errorlevel $errorLevel$ ; // Set number of lines per page, 0 == all lines on one page LIST n=$LinesPerPage$ ; // Set the assembler default radix HEX or DEC RADIX $Radix$ ; // Expand macro listings EXPAND ; // Eject a page now PAGE ; // Define processor to be used and include the processor specifics #ifdef _18c242_ PROCESSOR 18c242 #include ".\lib\18c242.inc" #endif #ifdef _18c252_ PROCESSOR 18c252 #include ".\lib\18c252.inc" #endif #ifdef _18c442_ PROCESSOR 18c442 #include ".\lib\18c442.inc" #endif #ifdef _18c452_ PROCESSOR 18c452 #include ".\lib\18c452.inc" #endif #ifdef _18f242_ PROCESSOR 18f242 #include ".\lib\18f242.inc" #endif #ifdef _18f252_ PROCESSOR 18f252 #include ".\lib\18f252.inc" #endif #ifdef _18f442_ PROCESSOR 18f442 #include ".\lib\18f442.inc" #endif #ifdef _18f452_ PROCESSOR 18f452 #include ".\lib\18f452.inc" #endif endMacro // ////////////////////////////////////////////////////////////////////////// // // Register setup : // // Uses register definitions from somewhere else, these must be // 4th constant definitions of the form : // // n constant XXXX_IniVal // // Where : // // n : a value // XXXX : a valid PIC18 register name - see processor dependent .INC file. // // Use as : // // InitReg XXXX // // Generates Code : // // movlw _XXXX_IniVal // movwf XXXX // // ////////////////////////////////////////////////////////////////////////// macro InitReg ( aName ) ( -- ) ; // Initialize '$aName$' movlw <@" $aName$">_IniVal movwf $aName$ endMacro // //////////////////////////////////////////////////////////////////////////// #ifdef PageCrossWarnOff // If PageCrossWarnOff is defined don't generate // 'crossing page boundary' messages for 4th .' #define PageWarnOff' // compiled code. .' ' #endif // //////////////////////////////////////////////////////////////////////////// macro List ( aFormat ) ( -- ) // Control assembly macro listings LIST $aFormat$ endMacro // //////////////////////////////////////////////////////////////////////////// macro HexFormat ( aFormat ) ( -- ) // Control the default assembler radix LIST F=$aFormat$ endMacro // //////////////////////////////////////////////////////////////////////////// macro Title ( aTitle ) ( -- ) // Sets a title for the assembler TITLE $aTitle$ endMacro // //////////////////////////////////////////////////////////////////////////// macro Page ( ) ( -- ) // Ejects a page in the assmbler output list file PAGE endMacro // //////////////////////////////////////////////////////////////////////////// macro Config ( aValue ) ( -- ) // Processor configuration word CONFIG $aValue$ endMacro // //////////////////////////////////////////////////////////////////////////// macro IdLoc ( aNum aParams ) ( -- ) // Processor ID location byte __IDLOCS _IDLOC$aNum$, $aParams$ endMacro // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// only Compiler definitions also Forth // Low level abstraction code and maro's // The compiler relies on these to be present // //////////////////////////////////////////////////////////////////////////// macro ValueBegin ( ) ( -- ) ; // =========================================== ; // ======== Value initialization code ======== ValueInit ; // Value initialization code is compiled here ; // Followed by the rest of ValueBegin ( ) SetBSRDefault ; // Setup BSR AddressToFsr0 SZero ; // Setup data stack AddressToFsr1 LZero ; // Setup loop stack endMacro // //////////////////////////////////////////////////////////////////////////// // Inbetween the compiler will generate value initialization code // //////////////////////////////////////////////////////////////////////////// macro ValueEnd ( MainBank ) ( -- ) goto <@" Main"> ; // Jump into the 4th [[Main]] function. ; // ======== End of value initialization code ======== ; // ================================================== endMacro // //////////////////////////////////////////////////////////////////////////// macro (ForceRomBank) ( Nr Address ) ( -- ) #// CS ; // (ForceRomBank) $Nr$ $Address$ ; // a NOOP for 18fXXX, it has no rom banking. endMacro // //////////////////////////////////////////////////////////////////////////// macro (colon) ( MLabel NLabel Bank ) ( -- ) #// CS ; // $Bank$:$NLabel$ (colon) call $MLabel$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (code) ( MLabel NLabel Bank ) ( -- ) #// CS ; // $Bank$:$NLabel$ (code) call $MLabel$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (semi) ( ) ( -- ) #// CS return ; // B/ ----> (;) endMacro // //////////////////////////////////////////////////////////////////////////// macro (seminoreturn) ( ) ( -- ) #// CS ; // (noreturn;) endMacro // //////////////////////////////////////////////////////////////////////////// macro (lit) ( Arg Sign ) ( -- b ) #// CS ; // literal $Sign$$Arg$ PushLit $Sign$D'$Arg$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (dlit) ( Arg Sign ) ( -- w ) #// CS ; // dliteral $Sign$$Arg$ PushLit ($Sign$D'$Arg$' >> 0) & D'255' PushLit ($Sign$D'$Arg$' >> 8) & D'255' endMacro // //////////////////////////////////////////////////////////////////////////// macro (tlit) ( Arg Sign ) ( -- t ) #// CS ; // tliteral $Sign$$Arg$ PushLit ($Sign$D'$Arg$' >> 0) & D'255' PushLit ($Sign$D'$Arg$' >> 8) & D'255' PushLit ($Sign$D'$Arg$' >> 16) & D'255' endMacro // //////////////////////////////////////////////////////////////////////////// macro (qlit) ( Arg Sign ) ( -- q ) #// CS ; // qliteral $Sign$$Arg$ PushLit ($Sign$D'$Arg$' >> 0) & D'255' PushLit ($Sign$D'$Arg$' >> 8) & D'255' PushLit ($Sign$D'$Arg$' >> 16) & D'255' PushLit ($Sign$D'$Arg$' >> 24) & D'255' endMacro // //////////////////////////////////////////////////////////////////////////// macro (str-constdef) ( Name Mangled Size Value ) ( -- ) #// CS $Mangled$ ; // str-constdef $Name$ db D'$Size$', "$Value$" endMacro // //////////////////////////////////////////////////////////////////////////// macro (data-constdef) ( Name Mangled Size Value ) ( -- ) #// CS $Mangled$ ; // data-constdef $Name$ db D'$Size$', $Value$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (str-constant) ( Name Mangled ) ( -- wRomAddr ) #// CS ; // str-constant $Name$ ; // ( -- wRomAddr ) PushLit ($Mangled$ >> 0) & D'255' PushLit ($Mangled$ >> 8) & D'255' endMacro // //////////////////////////////////////////////////////////////////////////// macro (constdef) ( Name Mangled Value Sign ) ( -- ) #// CS $Mangled$ equ $Sign$D'$Value$' ; // constant $Name$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (constant) ( Name Value Sign ) ( -- b ) #// CS ; // constant $Name$ ( $Sign$$Value$) PushLit $Sign$D'$Value$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (2constdef) ( Name Mangled Value Sign ) ( -- ) #// CS $Mangled$ equ $Sign$D'$Value$' ; // 2constant $Name$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (2constant) ( Name Value Sign ) ( -- w ) #// CS ; // 2constant $Name$ ( $Sign$$Value$) PushLit ($Sign$D'$Value$' >> 0) & D'255' PushLit ($Sign$D'$Value$' >> 8) & D'255' endMacro // //////////////////////////////////////////////////////////////////////////// macro (3constdef) ( Name Mangled Value Sign ) ( -- ) #// CS tripple constant definition <@" $Name$"> equ $Sign$D'$Value$' ; // 3constant [[$Name$]] endMacro // //////////////////////////////////////////////////////////////////////////// macro (3constant) ( Name Value Sign ) ( -- t ) #// CS Tripple constant invocation ; // 3constant [[$Name$]] ( $Sign$$Value$) PushLit ( <@" $Name$"> >> 0) & D'255' PushLit ( <@" $Name$"> >> 8) & D'255' PushLit ( <@" $Name$"> >> 16) & D'255' endMacro // //////////////////////////////////////////////////////////////////////////// macro (4constdef) ( Name Mangled Value Sign ) ( -- ) #// CS $Mangled$ equ $Sign$D'$Value$' ; // 4constant $Name$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (4constant) ( Name Value Sign ) ( -- q ) #// CS ; // 4constant $Name$ ( $Sign$$Value$) PushLit ($Sign$D'$Value$' >> 0 ) & D'255' PushLit ($Sign$D'$Value$' >> 8 ) & D'255' PushLit ($Sign$D'$Value$' >> 16) & D'255' PushLit ($Sign$D'$Value$' >> 24) & D'255' endMacro // //////////////////////////////////////////////////////////////////////////// macro (vardef) ( Name Mangled Value Bank ) ( -- ) #// CS $Mangled$ equ 256 * D'$Bank$' + D'$Value$' ; // variable $Name$ :: Bank = $Bank$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (variable) ( Name Mangled Value Bank ) ( -- wRamAddr ) #// CS ; // variable $Name$ ( $Bank$:$Value$) ; $Mangled$ PushLit D'$Value$' PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (2vardef) ( Name Mangled Value Bank ) ( -- ) #// CS $Mangled$ equ 256 * D'$Bank$' + D'$Value$' ; // 2variable $Name$ :: Bank = $Bank$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (2variable) ( Name Mangled Value Bank ) ( -- wRamAddr ) #// CS ; // 2variable $Name$ ( $Bank$:$Value$) ; $Mangled$ PushLit D'$Value$' PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (3vardef) ( Name Mangled Value Bank ) ( -- ) #// CS tripple variable definition <@" $Name$"> equ 256 * D'$Bank$' + D'$Value$' ; // 3variable [[$Name$]] :: Bank = $Bank$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (3variable) ( Name Mangled Value Bank ) ( -- wRamAddr ) #// CS Tripple variable invocation ; // 3variable [[$Name$]] ( $Bank$:$Value$) ; <@" $Name$"> PushLit D'$Value$' PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (4vardef) ( Name Mangled Value Bank ) ( -- ) #// CS $Mangled$ equ 256 * D'$Bank$' + D'$Value$' ; // 4variable $Name$ :: Bank = $Bank$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (4variable) ( Name Mangled Value Bank ) ( -- wRamAddr ) #// CS ; // 4variable $Name$ ( $Bank$:$Value$) ; $Mangled$ PushLit D'$Value$' PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (arraydef) ( Name Mangled Value Size Bank ) ( -- ) #// CS $Mangled$ equ 256 * D'$Bank$' + D'$Value$' ; // $Size$ Array $Name$ :: Bank = $Bank$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (array) ( Name Mangled Value Size Bank ) ( -- wRamAddr ) #// CS ; // $Size$ Array $Name$ ( $Bank$:$Value$) ; $Mangled$ PushLit D'$Value$' PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// Macro (fielddef) ( Name Mangled Value Sign ) ( -- ) #// CS Structure field definition <@" $Name$"> equ $Sign$D'$Value$' ; // Field $Name$ EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (field) ( Name Value Sign ) ( -- b ) #// CS Structue field invocation ; // Field $Name$ ( $Sign$$Value$) PushLit <@" $Name$"> EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (>field) ( Name Value Sign ) ( u1 u2 -- u3 ) #// CS Structure field offset calculation ; // >Field $Name$ ( $Sign$$Value$) ; // ( bBase -- bBase+bOffset ) PushLit <@" $Name$"> addwf postdec0, w ; // (+) ( u1 u2 -- u3 ) EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (s>field) ( Name Value Sign ) ( w -- w ) #// CS Structure field offset calculation ; // s>Field $Name$ ( $Sign$$Value$) ; // ( dBase -- dBase+dOffset ) PushLit ( <@" $Name$"> >> 0 ) & D'255' PushLit ( <@" $Name$"> >> 8 ) & D'255' call <@" d+"> EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (2fielddef) ( Name Mangled Value Sign ) ( -- ) #// CS Double field definition <@" $Name$"> equ $Sign$D'$Value$' ; // 2Field $Name$ EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (2field) ( Name Value Sign ) ( -- w ) #// CS Double field invocation ; // 2Field $Name$ ( $Sign$$Value$) PushLit ( <@" $Name$"> >> 0) & D'255' PushLit ( <@" $Name$"> >> 8) & D'255' EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (>2field) ( Name Value Sign ) ( w -- w ) #// CS Structure field offset calculation ; // >2Field $Name$ ( $Sign$$Value$) ; // ( dBase -- dBase+dOffset ) PushLit ( <@" $Name$"> >> 0 ) & D'255' PushLit ( <@" $Name$"> >> 8 ) & D'255' call <@" d+"> EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (s>2field) ( Name Value Sign ) ( b -- w ) #// CS Structure field offset calculation ; // s>2Field $Name$ ( $Sign$$Value$) ; // ( bBase -- bBase+dOffset ) PushLit 0 ; // perform u>ud PushLit ( <@" $Name$"> >> 0 ) & D'255' PushLit ( <@" $Name$"> >> 8 ) & D'255' call <@" d+"> EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (structdef) ( Name Mangled Value Sign ) ( -- ) #// CS Structure definition <@" $Name$"> equ $Sign$D'$Value$' ; // Struct $Name$ EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (struct) ( Name Value Sign ) ( -- b ) #// CS Structure invocation ; // Struct $Name$ ( $Sign$$Value$) PushLit <@" $Name$"> EndMacro // //////////////////////////////////////////////////////////////////////////// // ValueBegin and ValueEnd macro's are // automatically invoked by the pic4th compiler // //////////////////////////////////////////////////////////////////////////// macro (valuestartup) ( Name Mangled Address Bank Value Sign ) ( -- ) #// CS ; // (valuestartup) - value initialization ; // Value $Name$ ( $Bank$:$Address$) := $Sign$$Value$ ; $Mangled$ movlw $Sign$D'$Value$' movwf D'$Address$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (valuedef) ( Name Mangled Value Bank ) ( -- ) #// CS $Mangled$ equ 256 * D'$Bank$' + D'$Value$' ; // Value $Name$ :: Bank = $Bank$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (value) ( Name Mangled Address Bank Fetch ) ( -- b ) #// CS ; // (value) Value $Name$ ( $Bank$:$Address$) ; $Mangled$ PushLit D'$Address$' PushLit D'$Bank$' call $Fetch$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (to) ( Name Mangled ) ( b -- ) #// CS ; // =: $Name$ / To $Name$ ( b -- ) ; $Mangled$ PopReg $Mangled$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (InitLocalSpace) ( aLocalStart ) ( -- ) #// CS ; // Initialize the local data pointer (LDP) movlw D'$aLocalStart$' movwf LDP endMacro // //////////////////////////////////////////////////////////////////////////// macro (GetLocalSpace) ( anAmount ) ( -- ) #// CS ; // Reserve space ($anAmount$ bytes) for local variables. movwf tmp1 ; // Save TOS movf LDP, w ; // Get LDP ; // Add $anAmount$ to it addlw D'$anAmount$' movwf LDP ; // And store it movf tmp1, w ; // Restore TOS endMacro // //////////////////////////////////////////////////////////////////////////// macro (FreeLocalSpace) ( anAmount ) ( -- ) #// CS ; // Free space ($anAmount$ bytes) for local variables. movwf tmp1 ; // Save TOS movf LDP, w ; // Get LDP ; // Subtract $anAmount$ from it sublw D'$anAmount$' movwf LDP ; // And store it movf tmp1, w ; // Restore TOS endMacro // //////////////////////////////////////////////////////////////////////////// macro (locvar) ( Name Mangled Value Bank Sign ) ( -- wRamAddr ) #// CS ; // LocVar $Name$ ( $Bank$:$Sign$$Value$) ; $Mangled$ PushLit $Sign$D'$Value$' addwf LDP, w PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (loc2var) ( Name Mangled Value Bank Sign ) ( -- wRamAddr ) #// CS ; // Loc2Var $Name$ ( $Bank$:$Sign$$Value$) ; $Mangled$ PushLit $Sign$D'$Value$' addwf LDP, w PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (loc3var) ( Name Mangled Value Bank Sign ) ( -- wRamAddr ) #// CS Local tripple variable invocation ; // [[Loc3Var]] [[$Name$]] ( $Bank$:$Sign$$Value$) ; <@" $Name$"> PushLit $Sign$D'$Value$' addwf LDP, w PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (loc4var) ( Name Mangled Value Bank Sign ) ( -- wRamAddr ) #// CS ; // Loc4Var $Name$ ( $Bank$:$Sign$$Value$) ; $Mangled$ PushLit $Sign$D'$Value$' addwf LDP, w PushLit D'$Bank$' endMacro // //////////////////////////////////////////////////////////////////////////// macro (label) ( Label ) ( -- ) #// CS $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (goto) ( Label ) ( -- ) #// CS ; // (goto) $Label$ bra $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (jumpto) ( Name Mangled ) ( -- ) #// CS ; // (jumpto) $Name$ bra $Mangled$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (call) ( Label ) ( -- ) #// CS ; // (call) $Label$ call $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// code ((fbranch)) ( f -- ) #// CS PopReg tmp1 ; // Pop Flag into tmp1 movf tmp1, f ; // To set or clear Z flag return endCode // //////////////////////////////////////////////////////////////////////////// macro (begin) ( Label ) ( -- ) #// CS ; // (begin) - a label $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (until) ( Label ) ( -- ) #// CS ; // (until) - branch if Z flag set fBranch $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (again) ( Label ) ( -- ) #// CS ; // (again) - unconditional branch bra $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (while) ( Label ) ( -- ) #// CS ; // (while) - branch if Z flag set fBranch $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (repeat) ( Label1 label2 ) ( -- ) #// CS ; // (repeat) - unconditional branch bra $Label1$ $Label2$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (if) ( Label ) ( -- ) #// CS ; // (if) - branch if Z flag set fBranch $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (else) ( Label1 Label2 ) ( -- ) #// CS ; // (else) - unconditional branch bra $Label2$ $Label1$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (then) ( Label ) ( -- ) #// CS ; // (then) or (endif) - a label $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (case) ( ) ( -- ) #// CS ; // (case)- place holder only endMacro // //////////////////////////////////////////////////////////////////////////// macro (endcase) ( Label ) ( -- ) #// CS ; // (endcase) - a label $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// code ((of)) ( b1 b2 -- b1 | ) #// CS PopReg tmp1 ; // Get & drop n2 into tmp1 cpfseq tmp1 ; // S// n1 == n2 bra of_uneq ; // B/ n1 <> n2 ; // n1 == n2 Drop ; // Drop n1 bcf Status, Z ; // Flag match return of_uneq bsf Status, Z ; // Flag no match return endCode // //////////////////////////////////////////////////////////////////////////// macro (of) ( Label ) ( -- ) #// CS ; // (of) - branch if Z flag set fBranch $Label$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (endof) ( Label1 Label2 ) ( -- ) #// CS ; // (endof) - unconditional branch bra $Label1$ $Label2$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (table) ( ) ( -- ) #// CS ; // (table) bcf wreg, 7 rlncf wreg addwf pcl, f endMacro deprecated // //////////////////////////////////////////////////////////////////////////// macro (TableElt) ( Arg Sign ) ( -- ) #// CS ; // (TableElt) retlw $Sign$D'$Arg$' endMacro deprecated // //////////////////////////////////////////////////////////////////////////// macro ((table)) ( Arg Bank ) ( -- ) #// CS ; // ((table)) $Bank$:$Arg$ movwf tmp1 movlw ($Arg$ >> 0) & 0xff addwf tmp1, w movlw ($Arg$ >> 8) & 0xff btfsc status, C addlw D'1' movwf pclath movf tmp1, w call $Arg$ endMacro deprecated // //////////////////////////////////////////////////////////////////////////// code ((loop)) ( -- ) #// CS PushNothing ; // Save wreg incf indf1 ; // Advance index movf postinc1, w ; // get index into wreg xorwf indf1, w ; // Compare with limit bnz LoopMore ; // B/ Index <> Limit LoopNoMore ; // Also used by [[(+loop)]] incf fsr1l, f ; // Index == Limit Drop ; // Restore wreg bcf status, Z ; // signal index = limit return LoopMore ; // Also used by [[(+loop)]] decf fsr1l, f ; // restore Loop stack pointer Drop ; // Restore wreg bsf status, Z ; // signal index <> limit return endCode // //////////////////////////////////////////////////////////////////////////// code ((+loop)) ( b -- ) #// CS addwf indf1 ; // Index + inc -> Index movf postinc1, w ; // Get index LSP++ subwf indf1, W ; // Limit - Index bc LoopMore ; // B/ Carry , Not done, see [[((loop))]] bra LoopNoMore ; // B/ No carry, done , see [[((loop))]] endCode resources ((loop)) endResources // //////////////////////////////////////////////////////////////////////////// code ((do)) ( bLimit bStart -- ) #// CS PopReg tmp1 ; // Start into tmp1 dodo ; // entry point for [[((?do))]] if loop taken PopReg tmp2 ; // Limit into tmp2 LsPushReg tmp2 ; // Limit on loop stack LsPushReg tmp1 ; // Start on loop stack (as Index) bcf status, z ; // Return with zero flag cleared return ; // B/ ----> done (loop taken) endCode // //////////////////////////////////////////////////////////////////////////// code ((?do)) ( bLimit bStart -- ) #// CS PopReg tmp1 ; // bStart into tmp1 cpfseq indf1 ; // S/ Start = Limit bra dodo ; // B/ start <> Limit, perform [[((do))]] Drop ; // start = limit : drop bLimit bsf status, z ; // Return with zero flag set (loop skipped) return ; // B/ ----> done endCode resources ((do)) endResources // //////////////////////////////////////////////////////////////////////////// macro (do) ( SkipLabel LoopLabel ) ( bLimit bStart -- ) #// CS ; // (do) call <@" ((do))"> $LoopLabel$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (?do) ( SkipLabel LoopLabel ) ( bLimit bStart -- ) #// CS ; // (?do) : check if limit is count, if so skip loop call <@" ((?do))"> fBranch $SkipLabel$ $LoopLabel$ endMacro // //////////////////////////////////////////////////////////////////////////// macro (loop) ( LoopLabel SkipLabel ) ( -- ) #// CS ; // (loop) branch if Z flag set fBranch $LoopLabel$ $SkipLabel$ endMacro // //////////////////////////////////////////////////////////////////////////// code (Leave) ( -- ) #// CS PushNothing ; // Save wreg incf fsr1l ; // Point to limit decf postdec1, w ; // Get limit, dec limit, result into wreg movwf indf1 ; // Store limit - 1 as index Drop return endCode // //////////////////////////////////////////////////////////////////////////// Code ((try)) ( tRomAddr_REVERSED -- ) #// CS Helper for [[(try)]] ; // create (except) frame on return stack ; // ( tRomAddress -- ) [ -- (except) ] ; // >r addr_except_low PopReg tmp1 LsPushReg tmp1 ; // >r addr_except_high PopReg tmp1 LsPushReg tmp1 ; // >r addr_except_upper PopReg tmp1 LsPushReg tmp1 ; // >r stkptr LsPushReg stkptr ; // >r wreg LsPushReg wreg ; // >r data stack pointer LsPushReg fsr0l LsPushReg fsr0h AddExceptionFrame ; // Link in a new exception frame ; // Exception frame as on loop stack. ; // The loop stack grows downwards and uses fsr1. ; // On pussh first fsr1 is decremented then the new ; // value is stored into the stack. ; // ; // +--> | prev_exc_frame | ---- a possible previous frame (old_EFP ; // | +-------------------+ is zero for outermost frame). ; // | | | -+-- possible loop stack data from do..loop or >r ; // | ~ ~ -+ ; // | | | -+ ; // | +-------------------+ ; // | | addr_except low | -+-- ROM address of ((except)) to invoke ; // | | addr_except high | -+ ; // | | addr_except upper | -+ ; // | | old_stkptr | ---- Old return stack pointer ; // | | old_wreg | ---- Value that was on top of old stack ; // | | old_data_sp low | -+-- old data stack imcluding wreg ; // | | old_data_sp high | -+ ; // +-<- | old_EFP low | +---------+------+ ; // +-<- | old_EFP high | <--- | new EFP | fsr1 | ; // +-------------------+ +---------+------+ return ; // B/ ----> done EndCode // //////////////////////////////////////////////////////////////////////////// Code ((raise)) ( bException -- bException ) #// CS Helper for [[(raise)]] ; // Should check for original data stack corruption here ; // that is, when we have a relative stack underflow ; // that's definitly no good. ; // ; // Use the current (except) frame to determine ; // a jump to the nearest (except) handler. ; // Exception frame as on loop stack ; // ; // +--> | prev_frame | ; // | +-------------------+ ; // | | | ; // | ~ ~ ; // | | | ; // | +-------------------+ ; // | | addr_except low | -+-- ROM address of ((except)) to invoke ; // | | addr_except high | -+ ; // | | addr_except upper | -+ ; // | | old_stkptr | ---- Old return stack pointer ; // | | old_wreg | ---- Value that was on top of old stack ; // | | old_data_sp low | -+-- old data stack imcluding wreg ; // | | old_data_sp high | -+ ; // +-<- | old_EFP low | +-----+ ; // +-<- | old_EFP high | <--- + EFP | ; // +-------------------+ +-----+ ; // | | ; // ~ ~ +-----+ ; // | | <--- + fsr1| ; // +-----+ SetBsrDefault ; // For 4th execution BSR should have its default value movwf tmp1 ; // Keep bException in tmp1 RemoveExceptionFrame ; // Unwind one exception level LsPopReg fsr0h ; // restore data stack pointer LsPopReg fsr0l LsPopReg wreg ; // restore wreg disable ; // Interrupts off LsPopReg stkptr ; // Pop old stkptr (call stack pointer) back LsPopReg wreg ; // Pop (except) handler from loop stack movwf tosu LsPopReg wreg movwf tosh LsPopReg wreg movwf tosl enable ; // Interrupts back on PushReg tmp1 ; // Repush bException on restored data stack ; // Exception frame as on loop stack ; // +-----+------+ ; // | prev_frame | <--- | EFP | fsr1 | ; // +-------------------+ +-----+------+ ; // | | ; // ~ ~ ; // | | ; // +-------------------+ ; // | addr_except low | ; // ~ ~ return ; // B/ ----> Returns to (except) or (finally) handler EndCode // //////////////////////////////////////////////////////////////////////////// Code ((no_except)) ( -- ) #// CS Helper for (except) and [[(finally)]] ; // Discard one (except) frame ; // Exception frame as on loop stack ; // ; // +--> | prev_frame | ; // | +-------------------+ ; // | | | ; // | ~ ~ ; // | | | ; // | +-------------------+ ; // | | addr_except low | -+-- ROM address of ((except)) to invoke ; // | | addr_except high | -+ ; // | | addr_except upper | -+ ; // | | old_stkptr | ---- Old return stack pointer ; // | | old_wreg | ---- Value that was on top of old stack ; // | | old_data_sp low | -+-- old data stack imcluding wreg ; // | | old_data_sp high | -+ ; // +-<- | old_EFP low | +-----+ ; // +-<- | old_EFP high | <--- + EFP | ; // +-------------------+ +-----+ ; // | | ; // ~ ~ +-----+ ; // | | <--- + fsr1| ; // +-----+ RemoveExceptionFrame ; // Unwind one exception level LsFree 7 ; // Drop old_data_sp, old_wreg and addr_except ; // Exception frame as on loop stack ; // +-----+------+ ; // | prev_frame | <--- | EFP | fsr1 | ; // +-------------------+ +-----+------+ ; // | | ; // ~ ~ ; // | | ; // +-------------------+ ; // | addr_except low | ; // ~ ~ return ; // B/ ----> done EndCode // //////////////////////////////////////////////////////////////////////////// Macro (try) ( aTryLabel ) ( -- ) #// CS Compiled [[try]] ; // (try) ( -- ) PushLit (( $aTryLabel$) >> 16) & 0xff ; // Setup a fake return address for (raise) PushLit (( $aTryLabel$) >> 8) & 0xff ; // long jump to (except) handler PushLit (( $aTryLabel$) >> 0) & 0xff ; // using REVERSED push call <@" ((try))"> ; // ((try)) Create (except) frame on return stack ; // ( tRomAddr -- ) [ -- tRomAddr dDSP ] ; // end (try) ( -- ) [ -- tRomAddr dDSP ] EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (except) ( aTryLabel anEndLabel ) ( b -- b ) #// CS Compiled [[except]] ; // (except) ( bException | -- bException | ) ; // OK :: We fell trough, no exception, nothing on stack ; // ( ) call <@" ((no_except))"> ; // ((no_except)) remove (except) frame ; // B/ skip to (endtry) bra $anEndLabel$ $aTryLabel$ ; // EXCEPTION :: We came in thhrough a Raise action, exception on stack ; // ( bException ) ; // end ( except) EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (finally) ( aTryLabel aDummyForCompatibiltyReasons ) ( b -- ) #// CS Compiled [[finally]] ; // (finally) ( bException | -- bException | ) ; // OK :: We fell trough, no exception, nothing on stack ; // ( ) call <@" ((no_except))"> ; // ((no_except)) remove(except) frame PushLit 0 ; // Signal 'no exception' ; // (finally) Fall through to $aTryLabel$ $aTryLabel$ ; // EXCEPTION :: We came in through a Raise action, exception on stack ; // or we fell having no exception, zero on stack ; // ( bException ) Drop ; // But just forget about it for now. ; // (This should be re-raised at EndTry) ; // end ( finally) EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (endtry) ( anEndLabel ) ( -- ) #// CS Compiled [[endTry]] ; // (endtry), place holder $anEndLabel$ EndMacro // //////////////////////////////////////////////////////////////////////////// Macro (raise) ( ) ( b -- ) #// CS Compiled [[Raise]] ; // (raise) ( bExceptionOnCurrentDataStack -- bExceptionOnOldDataStack ) [ tRomAddr dDSP -- ] call <@" ((raise))"> ; // ((raise)) jump to (except) or (finally) handler ; // through (except) frame on return stack EndMacro // //////////////////////////////////////////////////////////////////////////// macro (+) ( ) ( u1 u2 -- u3 ) #// CS addwf postdec0, w ; // (+) ( u1 u2 -- u3 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (-) ( ) ( u1 u2 -- u3 ) #// CS subwf postdec0, w ; // (-) ( u1 u2 -- u3 ) endMacro // //////////////////////////////////////////////////////////////////////////// code (*) ( u1 u2 -- u3 ) #// CS PopReg tmp1 mulwf tmp1 movf prodl, w return endCode // //////////////////////////////////////////////////////////////////////////// code (/) ( u1 u2 -- u3 ) #// CS ; // also calculates remainder, ; // but we don't care about that! clrf tmp1 ; // remainder movwf tmp3 ; // u2 movlw D'8' ; // loop counter movwf tmp2 ; // to index slash_0 rlcf indf0, w ; // rotate u1 rlcf tmp1, f ; // into remainder movf tmp3, w ; // get u2 subwf tmp1, f ; // Try to subtract bc slash_1 ; // B/ subtract did work, carry is set addwf tmp1, f ; // subtract did not work, so add it again bcf status, C ; // and clear carry slash_1 rlcf indf0, f ; // result in indf0 decfsz tmp2 , f bra slash_0 movf postdec0, w ; // get result to TOS return endCode // //////////////////////////////////////////////////////////////////////////// code (/Mod) ( bDividend bDivisor -- bQuotient bRemainder ) #// CS ; // /////////////////////////////////////////////////////////////////////// ; // Function : /Mod ( bDividend bDivisor -- Quotient Remainder ) ; // Input : bDividend : 8 bits unsigned - high byte on top ; // : bDivisor : 8 bits unsigned - high byte on top ; // Output : Quotient : 8 bits unsigned - high byte on top ; // : Remainder : 8 bits unsigned - high byte on top ; // Description : 8 / 8 -> 8 bits unsigned divide with remainder ; // Remarks : Quotient := bDividend Div bDivisor ; // : Remainder := bDividend Mod bDivisor ; // /////////////////////////////////////////////////////////////////////// ; // ; // From Zilog Z8 Family Design Handbook, june 1988 ; // ; // A programmers guide to the Z8 microcomputer, ; // Z8 subroutine library, Application note ; // page 211. ; // ; // Adapted from 16 / 16 -> 16 + 16 algorithm above ; // ; // This is a 8 / 8 -> 8 + 8 udiv routine ; // ; // /////////////////////////////////////////////////////////////////////// ; // Pop arguments from stack to helper variables PopReg <@" Divisor"> ; // pop bDivisor into divisor ( bDividend ) movwf <@" Quotient"> ; // bDividend into Quotient clrf <@" Remainder"> movlw 8 ; // ld d32_LEN, #8 !LOOP COUNTER! movwf tmp2 bcf Status, C ; // rcf !carry = 0! ; // Then go for it dlp_8 rlcf <@" Quotient">, f ; // rlc qout rlcf <@" Remainder">, f ; // rlc rem bc subt_8 ; // B/ C not clear movf <@" Divisor">, w ; // See if we can subtract subwf <@" Remainder">, w bnc skp_8 ; // B/ carry not set, skip subtraction subt_8 movf <@" Divisor">, w ; // sub rem, dvsr subwf <@" Remainder">, f bsf Status, C ; // scf skp_8 decfsz tmp2, f ; // djnz d16_LEN, dlp_16 bra dlp_8 ; // !no flags affected! rlcf <@" Quotient">, f ; // rlc quot ; // Now copy results to stack movf <@" Quotient">, w ; // ( bQuotient ) PushReg <@" Remainder"> ; // ( bQuotient bRemainder ) return endCode // //////////////////////////////////////////////////////////////////////////// macro (and) ( ) ( u1 u2 -- u3 ) #// CS andwf postdec0, w ; // (and) ( b1 b2 -- b3 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (or) ( ) ( u1 u2 -- u3 ) #// CS iorwf postdec0, w ; // (or) ( b1 b2 -- b3 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (xor) ( ) ( u1 u2 -- u3 ) #// CS xorwf postdec0, w ; // (xor) ( b1 b2 -- b3 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (drop) ( ) ( b -- ) #// CS ; // drop ( b -- ) Drop endMacro // //////////////////////////////////////////////////////////////////////////// macro (dup) ( ) ( b -- b b ) #// CS ; // (dup) ( b -- b b ) Dup endMacro // //////////////////////////////////////////////////////////////////////////// code (swap) ( b1 b2 -- b2 b1 ) #// CS PopReg tmp2 PopReg tmp1 PushReg tmp2 PushReg tmp1 return endCode // //////////////////////////////////////////////////////////////////////////// macro (True) ( ) ( -- f ) #// CS PushLit True ; // (True) ( -- f ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (False) ( ) ( -- f ) #// CS PushLit False ; // (False) ( -- f ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (Space) ( ) ( -- b ) #// CS PushLit 0x20 ; // (space) ( -- b ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (negate) ( ) ( b -- b ) #// CS sublw D'0' ; // negate ( b1 -- b2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro (not) ( ) ( b -- b ) #// CS xorlw 0xff ; // Not ( b1 -- b2 ) endMacro // //////////////////////////////////////////////////////////////////////////// code (=) ( b1 b2 -- f ) #// CS subwf postdec0, f btfsc status, Z retlw True retlw False endCode // //////////////////////////////////////////////////////////////////////////// code (<>) ( b1 b2 -- f ) #// CS subwf postdec0, f btfsc status, Z retlw False retlw True endCode // //////////////////////////////////////////////////////////////////////////// code (<) ( u1 u2 -- f ) #// CS subwf postdec0, f movlw True ; // assume true btfss status, Z ; // if set then always false btfsc status, C ; // if not then also analyze carry clrf wreg ; // false flag return endCode // //////////////////////////////////////////////////////////////////////////// : (>) ( u1 u2 -- f ) #// CS Swap < ; // //////////////////////////////////////////////////////////////////////////// : (<=) ( u1 u2 -- f ) #// CS > Not ; // //////////////////////////////////////////////////////////////////////////// : (>=) ( u1 u2 -- f ) #// CS < Not ; // //////////////////////////////////////////////////////////////////////////// code (?dup) ( b -- b b | b -- 0 ) #// CS iorlw D'0' btfsc status, Z return Dup return endCode // //////////////////////////////////////////////////////////////////////////// macro (2drop) ( ) ( w -- ) #// CS Drop ; // (2drop) ( w -- ) Drop endMacro // //////////////////////////////////////////////////////////////////////////// code (over) ( b1 b2 -- b1 b2 b1 ) #// CS movff indf0, tmp1 PushReg tmp1 return endCode // //////////////////////////////////////////////////////////////////////////// : (2dup) ( w -- w w ) #// CS Over Over ; // //////////////////////////////////////////////////////////////////////////// macro (lshift) ( ) ( b -- b ) #// CS rlncf wreg ; // lshift ( b1 -- b2 ) bcf wreg, 0 endMacro // //////////////////////////////////////////////////////////////////////////// macro (rshift) ( ) ( b -- b ) #// CS rrncf wreg ; // rshift ( b1 -- b2 ) bcf wreg, 7 endMacro // //////////////////////////////////////////////////////////////////////////// code (<<) ( b1 b2 -- b3 ) #// CS PopReg tmp1 ; // Shift b1 left over b2 positions shllp bcf Status, C rlcf wreg, f decfsz tmp1 bra shllp return endCode // //////////////////////////////////////////////////////////////////////////// code (>>) ( b1 b2 -- b3 ) #// CS PopReg tmp1 ; // Shift b1 right over b2 positions shrlp bcf Status, C rrcf wreg, f decfsz tmp1 bra shrlp return endCode // //////////////////////////////////////////////////////////////////////////// code (2Over) ( w1 w2 -- w1 w2 w1 ) #// CS PopReg tmp4 PopReg tmp3 PopReg tmp2 movwf tmp1 PushReg tmp2 PushReg tmp3 PushReg tmp4 PushReg tmp1 PushReg tmp2 return endCode // //////////////////////////////////////////////////////////////////////////// code (rot) ( b1 b2 b3 -- b2 b3 b1 ) #// CS PopReg tmp3 PopReg tmp2 PopReg tmp1 PushReg tmp2 PushReg tmp3 PushReg tmp1 return endCode // //////////////////////////////////////////////////////////////////////////// alias (rot) (+rot) #// CS (rot) also known as (+rot) // //////////////////////////////////////////////////////////////////////////// code (-rot) ( b1 b2 b3 -- b3 b1 b2 ) #// CS PopReg tmp3 PopReg tmp2 PopReg tmp1 PushReg tmp3 PushReg tmp1 PushReg tmp2 return endCode // //////////////////////////////////////////////////////////////////////////// code (pick) ( u1 -- u2 ) #// CS ; // Push u:th entry PushNothing sublw D'0' ; // negate movf plusw0, w ; // w = offset of reqd. byte, return ; // 0th byte references TOS endCode // //////////////////////////////////////////////////////////////////////////// code (put) ( b u -- ) #// CS ; // u th byte of stack replaced by value b ; // 0th byte = top of stack sublw D'0' ; // negate PopReg tmp1 ; // Get offset movwf tmp2 ; // Get velue to put movf tmp1, w ; // Offset to wreg movff tmp2, plusw0 ; // Put value PopReg wreg ; // Pop top item of stack into wreg return endCode // //////////////////////////////////////////////////////////////////////////// code (abs) ( b -- u ) #// CS btfsc wreg, 7 sublw D'0' return endCode // //////////////////////////////////////////////////////////////////////////// code (Max) ( u1 u2 -- u3 ) #// CS PopReg tmp1 cpfslt tmp1 ; // S/ tmp1 < wreg , so wreg is maximum movf tmp1, w ; // tmp1 >= wreg, so tmp1 is maximum return endCode // //////////////////////////////////////////////////////////////////////////// code (Min) ( u1 u2 -- u3 ) #// CS PopReg tmp1 cpfsgt tmp1 ; // S/ tmp1 > wreg , so wreg is minimum movf tmp1, w ; // tmp1 <= wreg, so tmp1 is minimum return endCode // //////////////////////////////////////////////////////////////////////////// code (@) ( wRamAddr -- b ) #// CS [Fetch] PopReg fsr2h ; // Get bank PopReg fsr2l ; // Get address PushReg indf2 ; // dereference return endCode // //////////////////////////////////////////////////////////////////////////// code (!) ( b wRamAddr -- ) #// CS [Store] PopReg fsr2h ; // Get bank PopReg fsr2l ; // Get addrress PopReg indf2 ; // Get and store data return endCode // //////////////////////////////////////////////////////////////////////////// code (+!) ( b wRamAddr -- ) #// CS PopReg fsr2h PopReg fsr2l addwf indf2 Drop return endCode // //////////////////////////////////////////////////////////////////////////// code (-!) ( b wRamAddr -- ) #// CS PopReg fsr2h PopReg fsr2l subwf indf2 Drop return endCode // //////////////////////////////////////////////////////////////////////////// macro (Default) ( ) ( -- ) #// CS ; // Default case endMacro // //////////////////////////////////////////////////////////////////////////// macro (Exit) ( ) ( -- ) #// CS return ; // /B --> Exit endMacro // //////////////////////////////////////////////////////////////////////////// macro (I) ( ) ( -- u ) #// CS PushReg indf1 ; // I ( -- u ) Get inner loop index endMacro // //////////////////////////////////////////////////////////////////////////// code (I') ( -- u ) #// CS PushLit D'1' ; // Get inner loop limit movf plusw1, w return endCode // //////////////////////////////////////////////////////////////////////////// code (J) ( -- u ) #// CS PushLit D'2' ; // Get 2nd loop index movf plusw1, w return endCode // //////////////////////////////////////////////////////////////////////////// code (J') ( -- u ) #// CS PushLit D'3' ; // Get 2nd loop limit movf plusw1, w return endCode // //////////////////////////////////////////////////////////////////////////// code (K) ( -- u ) #// CS PushLit D'4' ; // Get 3d loop index movf plusw1, w return endCode // //////////////////////////////////////////////////////////////////////////// code (R>) ( -- b ) #// CS [ b -- ] LsPopReg tmp1 PushReg tmp1 return endCode // //////////////////////////////////////////////////////////////////////////// code (>R) ( b -- ) #// CS [ -- b ] PopReg tmp1 LsPushReg tmp1 return endCode // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// Only Forth Definitions also Compiler // Normal user words - the library words // //////////////////////////////////////////////////////////////////////////// macro BreakPoint ( aMsg ) ( -- ) nop ; BREAKPOINT $aMsg$ endMacro // //////////////////////////////////////////////////////////////////////////// macro Nop ( ) ( -- ) nop ; // Nop ( -- ) endMacro // //////////////////////////////////////////////////////////////////////////// macro ClrWDT ( ) ( -- ) clrwdt ; // ClrWDT ( -- ) endMacro // //////////////////////////////////////////////////////////////////////////// macro Sleep ( ) ( -- ) sleep ; // Sleep ( -- ) endMacro // //////////////////////////////////////////////////////////////////////////// macro Reset ( ) ( -- ) Reset ; // Reset ( -- ) endMacro // //////////////////////////////////////////////////////////////////////////// macro Disable ( ) ( -- ) ; // Disable ( -- ), disable interrupts Disable endMacro // //////////////////////////////////////////////////////////////////////////// macro Enable ( ) ( -- ) ; // Enable ( -- ) // enable interrupts Enable endMacro // //////////////////////////////////////////////////////////////////////////// code d@ ( wRamAddr -- w ) [DFetch] PopReg fsr2h ; // Get bank selector into fsr2h PopReg fsr2l PushReg postinc2 PushReg indf2 return endCode // //////////////////////////////////////////////////////////////////////////// code dabs ( d -- ud ) ; // 16 bits Abs btfss wreg, 7 bra dabs_done comf indf0, f incf indf0, f btfsc Status, z decf wreg, f comf wreg, f dabs_done Return endCode // //////////////////////////////////////////////////////////////////////////// code Negative? ( b -- f ) btfss wreg, 7 retlw False retlw True endCode // //////////////////////////////////////////////////////////////////////////// code dNegative? ( d -- f ) SwapDrop bra <@" Negative?"> endCode // //////////////////////////////////////////////////////////////////////////// code qNegative? ( q -- f ) SwapDrop SwapDrop bra <@" dNegative?"> endCode // //////////////////////////////////////////////////////////////////////////// code dSwap ( w1 w2 -- w2 w1 ) PopReg tmp4 PopReg tmp3 PopReg tmp2 PopReg tmp1 PushReg tmp3 PushReg tmp4 PushReg tmp1 PushReg tmp2 return endCode // //////////////////////////////////////////////////////////////////////////// code 2Pick ( b0 b1 b3 -- b0 b1 b2 b0 ) // Copy 3rd stack entry to top ; // Push 3rd entry PushNothing ; // Make room on stack movlw -D'2' ; // negated offset movf plusw0, w ; // w = offset of reqd. byte, return ; // 0th byte references TOS endCode // //////////////////////////////////////////////////////////////////////////// code 3Pick ( b0 b1 b2 b4 -- b0 b1 b2 b4 b0 ) // Copy 4th stack entry to top ; // Push 4th entry PushNothing ; // Make room on stack movlw -D'3' ; // negated offset movf plusw0, w ; // w = offset of reqd. byte, return ; // 0th byte references TOS endCode // //////////////////////////////////////////////////////////////////////////// code 4Pick ( b0 b1 b2 b3 b4 -- b0 b1 b2 b3 b4 b0 ) // Copy 5th stack entry to top ; // Push 5th entry PushNothing ; // Make room on stack movlw -D'4' ; // negated offset movf plusw0, w ; // w = offset of reqd. byte, return ; // 0th byte references TOS endCode // //////////////////////////////////////////////////////////////////////////// code a+ ( w1 u -- w2 ) decf fsr0l, f addwf postinc0, f Drop return endCode // //////////////////////////////////////////////////////////////////////////// macro 1a+ ( ) ( wRamAddr -- wRamAddr ) ; // 1a+ ( w1 -- w2 ) incf indf0, f endMacro // //////////////////////////////////////////////////////////////////////////// macro 2a+ ( ) ( wRamAddr -- wRamAddr ) ; // 2a+ ( w1 -- w2 ) incf indf0, f incf indf0, f endMacro // //////////////////////////////////////////////////////////////////////////// code 3a+ ( w1 -- w2 ) incf indf0, f incf indf0, f incf indf0, f return endCode // //////////////////////////////////////////////////////////////////////////// code 4a+ ( w1 -- w2 ) incf indf0, f incf indf0, f incf indf0, f incf indf0, f return endCode // //////////////////////////////////////////////////////////////////////////// code a- ( w1 u -- w2 ) decf fsr0l, f subwf postinc0, f Drop return endCode // //////////////////////////////////////////////////////////////////////////// macro 1a- ( ) ( wRamAddr -- wRamAddr ) ; // 1a- ( w1 -- w2 ) decf indf0, f endMacro // //////////////////////////////////////////////////////////////////////////// macro 2a- ( ) ( wRamAddr -- wRamAddr ) ; // 2a- ( w1 -- w2 ) decf indf0, f decf indf0, f endMacro // //////////////////////////////////////////////////////////////////////////// code 3a- ( w1 -- w2 ) decf indf0, f decf indf0, f decf indf0, f return endCode // //////////////////////////////////////////////////////////////////////////// code 4a- ( w1 -- w2 ) decf indf0, f decf indf0, f decf indf0, f decf indf0, f return endCode // ////////////////////////////////////////////////////////////////////////// // // Fetch Add contents of var at wAdr2 to wAdr1 // : @a+ ( wAdr1 wAdr2 -- wAdr3 ) @ a+ ; // ////////////////////////////////////////////////////////////////////////// // // Fetch b from wAdr + u // : a+@ ( wAdr u -- b ) a+ @ ; // ////////////////////////////////////////////////////////////////////////// // // Fetch b from wAdr1 + wAdr2 @ // : @a+@ ( wAdr1 wAdr2 -- b ) @ a+@ ; // ////////////////////////////////////////////////////////////////////////// // // Store b at wAdr + u // : a+! ( b wAdr u -- ) a+ ! ; // ////////////////////////////////////////////////////////////////////////// // // Store n at wAdr1 + wAdr2 @ // : @a+! ( b wAdr1 wAdd2 -- ) @ a+! ; // //////////////////////////////////////////////////////////////////////////// alias (2Drop) aDrop ( wAddr -- ) alias (2Dup) aDup ( wAddr -- wAddr wAddr ) alias (2Over) aOver ( wAddr1 wAddr2 -- wAddr1 wAddr2 wAddr1 ) alias dSwap aSwap ( wAddr1 wAddr2 -- wAddr2 wAddr1 ) alias dSwap (2Swap) ( wAddr1 wAddr2 -- wAddr2 wAddr1 ) alias (space) bl ( -- b ) // //////////////////////////////////////////////////////////////////////////// : adup@ ( wAdr -- wAdr u ) // Dup wAdr and fetch a value from there. aDup @ ; // //////////////////////////////////////////////////////////////////////////// : 3Drop ( t -- ) Drop 2Drop ; // //////////////////////////////////////////////////////////////////////////// : 4Drop ( q -- ) 2Drop 2Drop ; // //////////////////////////////////////////////////////////////////////////// : 3Dup ( t -- t t ) 2pick 2pick 2pick ; // //////////////////////////////////////////////////////////////////////////// : 4Dup ( q -- q q ) 2Over 2Over ; // //////////////////////////////////////////////////////////////////////////// code RomPtr! ( wRomAddr -- ) PopReg tblptrh Popreg tblptrl return endCode // //////////////////////////////////////////////////////////////////////////// code RomPtr@ ( -- wRomAddr ) Pushreg tblptrl PushReg tblptrh return endCode // //////////////////////////////////////////////////////////////////////////// macro RomPtr++ ( -- ) ( -- ) tblrd*+ ; // RomPtr++ ( -- ) endMacro // //////////////////////////////////////////////////////////////////////////// code Rom@ ( -- b ) tblrd* PushReg tablat return endCode // //////////////////////////////////////////////////////////////////////////// code []Rom@ ( bIndex -- b ) movff tblptrl, tmp1 ; // Save tablepointer movff tblptrh, tmp2 addwf tblptrl, f ; // Add bIndex to it clrf wreg addwfc tblptrh, f tblrd* ; // read bData byte movf tablat, w ; // return data in TOS movff tmp2, tblptrl ; // restore table pointer movff tmp1, tblptrh return endCode // //////////////////////////////////////////////////////////////////////////// code Rom@++ ( -- b ) tblrd*+ PushReg tablat return endCode // //////////////////////////////////////////////////////////////////////////// code ++Rom@ ( -- b ) tblrd+* PushReg tablat return endCode // //////////////////////////////////////////////////////////////////////////// code Rom@-- ( -- ) tblrd*- PushReg tablat return endCode // //////////////////////////////////////////////////////////////////////////// code Rom! ( b -- ) PopReg tablat tblwt* return endCode // //////////////////////////////////////////////////////////////////////////// code Rom!++ ( b -- ) PopReg tablat tblwt*+ return endCode // //////////////////////////////////////////////////////////////////////////// code ++Rom! ( b -- ) PopReg tablat tblwt+* return endCode // //////////////////////////////////////////////////////////////////////////// code Rom!-- ( b -- ) PopReg tablat tblwt*- return endCode // //////////////////////////////////////////////////////////////////////////// code RamPtr! ( wRamAddr -- ) PopReg <@" RamPtr"> + 1 Popreg <@" RamPtr"> + 0 return endCode // //////////////////////////////////////////////////////////////////////////// code RamPtr@ ( -- wRamAddr ) Pushreg <@" RamPtr"> + 0 PushReg <@" RamPtr"> + 1 return endCode // //////////////////////////////////////////////////////////////////////////// macro RamPtr++ ( ) ( -- ) incf <@" RamPtr"> + 0 ; // RamPtr++ ( -- ) endMacro // //////////////////////////////////////////////////////////////////////////// macro RamPtr-- ( ) ( -- ) decf <@" RamPtr"> + 0 ; // RamPtr-- ( -- ) endMacro // //////////////////////////////////////////////////////////////////////////// : Ram@ ( -- b ) RamPtr@ @ ; // //////////////////////////////////////////////////////////////////////////// : []Ram@ ( bIndex -- b ) RamPtr@ a+@ ; // //////////////////////////////////////////////////////////////////////////// : Ram@++ ( -- b ) Ram@ RamPtr++ ; // //////////////////////////////////////////////////////////////////////////// : ++Ram@ ( -- b ) RamPtr++ Ram@ ; // //////////////////////////////////////////////////////////////////////////// : Ram@-- ( -- b ) Ram@ RamPtr-- ; // //////////////////////////////////////////////////////////////////////////// : Ram! ( b -- ) RamPtr@ ! ; // //////////////////////////////////////////////////////////////////////////// : Ram!++ ( b -- ) Ram! RamPtr++ ; // //////////////////////////////////////////////////////////////////////////// : ++Ram! ( b -- ) RamPtr++ Ram! ; // //////////////////////////////////////////////////////////////////////////// : Ram!-- ( b -- ) Ram! RamPtr-- ; // //////////////////////////////////////////////////////////////////////////// code 1-! ( wRamAddr -- ) PopReg fsr2h PopReg fsr2l decf indf2, f return endCode // //////////////////////////////////////////////////////////////////////////// code 1+! ( wRamAddr -- ) PopReg fsr2h PopReg fsr2l incf indf2, f return endCode // //////////////////////////////////////////////////////////////////////////// code d! ( w wRamAddr -- ) PopReg fsr2h PopReg fsr2l PopReg tmp1 PopReg postinc2 movff tmp1, indf2 return endCode // //////////////////////////////////////////////////////////////////////////// code And! ( b wRamAddr -- ) PopReg fsr2h PopReg fsr2l andwf indf2 Drop return endCode // //////////////////////////////////////////////////////////////////////////// code Or! ( b wRamAddr -- ) PopReg fsr2h PopReg fsr2l iorwf indf2 Drop return endCode // //////////////////////////////////////////////////////////////////////////// code Xor! ( b wRamAddr -- ) PopReg fsr2h PopReg fsr2l xorwf indf2 Drop return endCode // //////////////////////////////////////////////////////////////////////////// code Dup! ( b wRamAddr -- b ) PopReg fsr2h PopReg fsr2l movwf indf2 return endCode // //////////////////////////////////////////////////////////////////////////// code True! ( wRamAddr -- ) PopReg fsr2h movwf fsr2l movlw True movwf indf2 Drop return endCode // //////////////////////////////////////////////////////////////////////////// code False! ( wRamAddr -- ) PopReg fsr2h movwf fsr2l movlw False movwf indf2 Drop return endCode // //////////////////////////////////////////////////////////////////////////// alias False! 0! ( wRamAddr -- ) // False! also known as 0! from now on alias True! ff! ( wRamAddr -- ) // True! also known as ff! from now on // //////////////////////////////////////////////////////////////////////////// code ^Xor ( wRamAddr1 wRamAddr2 -- ) ; // Indirect 8 bits xor of wRamAddr1^with wRamAddr^2 ; // result stored at wRamAddr1 movff fsr1l, tmp1 movff fsr1h, tmp2 PopReg fsr2h PopReg fsr2l PopReg fsr1h movwf fsr1l movf indf2, w xorwf indf1, f movff tmp1, fsr1l movff tmp2, fsr1h Drop return endCode // //////////////////////////////////////////////////////////////////////////// code ^Shl ( wRamAddr -- ) // Indirect left shift PopReg fsr2h PopReg fsr2l rlcf indf2 return endCode // //////////////////////////////////////////////////////////////////////////// code ^Shr ( wRamAddr -- ) // Indirect right shift PopReg fsr2h PopReg fsr2l rrcf indf2 return endCode // //////////////////////////////////////////////////////////////////////////// code ^rl ( wRamAddr -- ) // Indirect left rotate PopReg fsr2h PopReg fsr2l rlncf indf2 return endCode // //////////////////////////////////////////////////////////////////////////// code ^rr ( wRamAddr -- ) // Indirect right rotate PopReg fsr2h PopReg fsr2l rrncf indf2 return endCode // //////////////////////////////////////////////////////////////////////////// code Xor32 ( q q -- q ) PopReg tmp1 PopReg tmp2 PopReg tmp3 PopReg tmp4 xorwf tmp1, f Drop xorwf tmp2, f Drop xorwf tmp3, f Drop xorwf tmp4, w PushReg tmp3 PushReg tmp2 PushReg tmp1 return endCode // //////////////////////////////////////////////////////////////////////////// code <<32 ( q n -- q ) PopReg tmp1 PopReg tmp2 PopReg tmp3 PopReg tmp4 shl32lp bcf Status, C rlcf wreg rlcf tmp4 rlcf tmp3 rlcf tmp2 decfsz tmp1 bra shl32lp PushReg tmp4 PushReg tmp3 PushReg tmp2 return endCode // //////////////////////////////////////////////////////////////////////////// code >>32 ( q n -- q ) PopReg tmp1 PopReg tmp2 PopReg tmp3 PopReg tmp4 shr32lp bcf Status, C rrcf tmp2 rrcf tmp3 rrcf tmp4 rrcf wreg decfsz tmp1 bra shr32lp PushReg tmp4 PushReg tmp3 PushReg tmp2 return endCode // //////////////////////////////////////////////////////////////////////////// code qnegate ( q -- -q ) PopReg tmp4 PopReg tmp3 PopReg tmp2 sublw D'0' movwf tmp1 movlw 0 subwfb tmp2, f subwfb tmp3, f subwfb tmp4, f movf tmp1, w PushReg tmp2 PushReg tmp3 PushReg tmp4 return endCode // //////////////////////////////////////////////////////////////////////////// : d>r ( d -- ) swap >r >r ; // //////////////////////////////////////////////////////////////////////////// : dr> ( d -- ) r> r> swap ; // //////////////////////////////////////////////////////////////////////////// : q>r ( q -- ) dSwap d>r d>r ; // //////////////////////////////////////////////////////////////////////////// : qr> ( q -- ) dr> dr> dSwap ; // //////////////////////////////////////////////////////////////////////////// code Popq1 ( q -- ) PopReg tmp4 ; // Pop q PopReg tmp3 PopReg tmp2 PopReg tmp1 return endCode // //////////////////////////////////////////////////////////////////////////// code Pushq1 ( -- q ) PushReg tmp1 PushReg tmp2 PushReg tmp3 PushReg tmp4 return endCode // //////////////////////////////////////////////////////////////////////////// code Popq2 ( q -- ) PopReg <@" Quotient"> + 3 ; // Pop q PopReg <@" Quotient"> + 2 PopReg <@" Quotient"> + 1 PopReg <@" Quotient"> + 0 return endCode // //////////////////////////////////////////////////////////////////////////// code Pushq2 ( -- q ) PushReg <@" Quotient"> + 0 PushReg <@" Quotient"> + 1 PushReg <@" Quotient"> + 2 PushReg <@" Quotient"> + 3 return endCode // //////////////////////////////////////////////////////////////////////////// code Popq3 ( q -- ) PopReg <@" Remainder"> + 3 ; // Pop q PopReg <@" Remainder"> + 2 PopReg <@" Remainder"> + 1 PopReg <@" Remainder"> + 0 return endCode // //////////////////////////////////////////////////////////////////////////// code Pushq3 ( -- q ) PushReg <@" Remainder"> + 0 PushReg <@" Remainder"> + 1 PushReg <@" Remainder"> + 2 PushReg <@" Remainder"> + 3 return endCode // //////////////////////////////////////////////////////////////////////////// : 4rot ( q1 q2 q3 -- q2 q3 q1 ) Popq3 Popq2 Popq1 Pushq2 Pushq3 Pushq1 ; // //////////////////////////////////////////////////////////////////////////// : 4over ( q1 q2 -- q1 q2 q1 ) Popq2 Popq1 Pushq1 Pushq2 Pushq1 ; // //////////////////////////////////////////////////////////////////////////// : 4swap ( q1 q2 -- q2 q1 ) Popq2 Popq1 Pushq2 Pushq1 ; // //////////////////////////////////////////////////////////////////////////// code ^>>32 ( wRamAddr n -- ) ; // Indirect 32 bits right shift over n positions PopReg tmp1 ; // Shift wRamAddr^ right over n positions PopReg fsr2h ; // let fsr2 point to end of data (highest byte) shri32lp addlw 3 movwf fsr2l bcf Status, C ; // Clear carry rrcf postdec2, f rrcf postdec2, f rrcf postdec2, f rrcf indf2 , f movf fsr2l, w decfsz tmp1 bra shri32lp Drop return endCode // //////////////////////////////////////////////////////////////////////////// code ^<<32 ( wRamAddr n -- ) ; // Indirect 32 bits left shift over n positions PopReg tmp1 ; // Shift wRamAddr^ left over n positions PopReg fsr2h ; // let fsr2 popint to first (lowest) byte shli32lp movwf fsr2l bcf Status, C ; // Clear carry rlcf postinc2, f rlcf postinc2, f rlcf postinc2, f rlcf indf2 , f movf fsr2l, w addlw 3 decfsz tmp1 bra shli32lp Drop return endCode // //////////////////////////////////////////////////////////////////////////// code d+ ( wu1 wu2 -- wu3 ) PopReg tmp1 ; // Pop hi2 into tmp1, leaving lo2 in wreg decf fsr0l ; // point to lo1 addwf postinc0 ; // Add lo bytes (lo3), point to hi1 movf tmp1, w ; // get hi2 addwfc postdec0, w ; // Add hi bytes into w, point to lo3 return endCode // //////////////////////////////////////////////////////////////////////////// code d- ( wu1 wu2 -- wu3 ) PopReg tmp1 ; // Pop hi2 into tmp1, leaving lo2 in wreg decf fsr0l ; // point to lo1 subwf postinc0 ; // Sub lo bytes (lo3), point to hi1 movf tmp1, w ; // get hi2 subwfb postdec0, w ; // Sub hi bytes into w, point to lo3 return endCode // //////////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////////// macro 1+ ( ) ( b -- b ) addlw D'1' ; // 1+ ( u1 -- u3 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 2+ ( ) ( b -- b ) addlw D'2' ; // 2+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 3+ ( ) ( b -- b ) addlw D'3' ; // 3+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 4+ ( ) ( b -- b ) addlw D'4' ; // 4+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 5+ ( ) ( b -- b ) addlw D'5' ; // 5+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 6+ ( ) ( b -- b ) addlw D'6' ; // 6+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 7+ ( ) ( b -- b ) addlw D'7' ; // 7+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 8+ ( ) ( b -- b ) addlw D'8' ; // 8+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 9+ ( ) ( b -- b ) addlw D'9' ; // 9+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 10+ ( ) ( b -- b ) addlw D'10' ; // 10+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro '0'+ ( ) ( b -- b ) addlw 0x30 ; // '0'+ ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 1- ( ) ( b -- b ) addlw D'255' ; // 1- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 2- ( ) ( b -- b ) addlw D'254' ; // 2- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 3- ( ) ( b -- b ) addlw D'253' ; // 3- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 4- ( ) ( b -- b ) addlw D'252' ; // 4- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 5- ( ) ( b -- b ) addlw D'251' ; // 5- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 6- ( ) ( b -- b ) addlw D'250' ; // 6- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 7- ( ) ( b -- b ) addlw D'249' ; // 7- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 8- ( ) ( b -- b ) addlw D'248' ; // 8- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 9- ( ) ( b -- b ) addlw D'247' ; // 9- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro 10- ( ) ( b -- b ) addlw D'246' ; // 10- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// macro '0'- ( ) ( b -- b ) addlw 0xD0 ; // '0'- ( u1 -- u2 ) endMacro // //////////////////////////////////////////////////////////////////////////// code d= ( w1 w2 -- f ) PopReg tmp1 ; // u4 PopReg tmp2 ; // u3 PopReg tmp3 ; // u2 cpfseq tmp2 retlw False movf tmp3, w cpfseq tmp1 retlw False retlw True endCode // //////////////////////////////////////////////////////////////////////////// code d> ( wu1 wu2 -- f ) ; // Return True if N1 (u1,u2) > N2 (u3,u4) (or N2 < N1) PopReg tmp3 ; // Pop N2 PopReg tmp4 PopReg tmp1 ; // Pop N1 movwf tmp2 cpfslt16 tmp4, tmp2 ; // S/ N2 < N1 retlw False ; // Assumptionwrong, return false retlw True endCode // //////////////////////////////////////////////////////////////////////////// code d< ( wu1 wu2 -- f ) ; // Return True if N1 (u1,u2) < N2 (u3,u4) (or N2 > N1) PopReg tmp3 PopReg tmp4 PopReg tmp1 movwf tmp2 cpfslt16 tmp2, tmp4 retlw False retlw True endCode // ////////////////////////////////////////////////////////////////////////// : sd< ( sd sd -- f ) // Checked d- dNegative? ; // ////////////////////////////////////////////////////////////////////////// : sd> ( sd sd -- f ) // Checked dSwap sd< ; // //////////////////////////////////////////////////////////////////////////// : sd>= ( sd sd -- f ) sd< not ; // //////////////////////////////////////////////////////////////////////////// : sd<= ( sd sd -- f ) sd> not ; // //////////////////////////////////////////////////////////////////////////// code 0= ( b -- f ) iorlw D'0' btfsc status, Z retlw True retlw False endCode // //////////////////////////////////////////////////////////////////////////// code 1= ( b -- f ) decfsz wreg retlw False retlw True endCode // //////////////////////////////////////////////////////////////////////////// code 0<> ( b -- f ) iorlw D'0' btfsc status, Z retlw False retlw True endCode // //////////////////////////////////////////////////////////////////////////// : 0< ( b -- f ) $80 and 0<> ; // //////////////////////////////////////////////////////////////////////////// macro u>ud ( ) ( b -- w ) PushLit D'0' ; // u>ud ( u -- wu ) endMacro // //////////////////////////////////////////////////////////////////////////// code s>d ( b -- w ) // with sign extension PushNothing btfsc indf0, 7 retlw D'255' retlw D'0' endCode // //////////////////////////////////////////////////////////////////////////// alias 0d ud>uq ( wu -- qu ) // unsigned // //////////////////////////////////////////////////////////////////////////// code d>q ( w -- q ) // with sign extension PushLit D'0' btfsc indf