/***********************************************************************/ /* */ /* startup_SAM7S.S: // assembler tests working toward a forth kernel. /***********************************************************************/ // *** Startup Code (executed after Reset) *** // Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs .equ Mode_USR, 0x10 .equ Mode_FIQ, 0x11 .equ Mode_IRQ, 0x12 .equ Mode_SVC, 0x13 .equ Mode_ABT, 0x17 .equ Mode_UND, 0x1B .equ Mode_SYS, 0x1F .equ I_Bit, 0x80 /* when I bit is set, IRQ is disabled */ .equ F_Bit, 0x40 /* when F bit is set, FIQ is disabled */ // Internal Memory Base Addresses .equ FLASH_BASE, 0x00100000 .equ RAM_BASE, 0x00200000 /* // Stack Configuration // Top of Stack Address <0x0-0xFFFFFFFF:4> // Stack Sizes (in Bytes) // Undefined Mode <0x0-0xFFFFFFFF:4> // Supervisor Mode <0x0-0xFFFFFFFF:4> // Abort Mode <0x0-0xFFFFFFFF:4> // Fast Interrupt Mode <0x0-0xFFFFFFFF:4> // Interrupt Mode <0x0-0xFFFFFFFF:4> // User/System Mode <0x0-0xFFFFFFFF:4> // // */ .equ Top_Stack, 0x00210000 .equ UND_Stack_Size, 0x00000004 .equ SVC_Stack_Size, 0x00000100 .equ ABT_Stack_Size, 0x00000004 .equ FIQ_Stack_Size, 0x00000004 .equ IRQ_Stack_Size, 0x00000100 .equ USR_Stack_Size, 0x00000100 // Embedded Flash Controller (EFC) definitions .equ EFC_BASE, 0xFFFFFF00 /* EFC Base Address */ .equ EFC_FMR, 0x60 /* EFC_FMR Offset */ /* // Embedded Flash Controller (EFC) // FMCN: Flash Microsecond Cycle Number <0-255> // Number of Master Clock Cycles in 1us // FWS: Flash Wait State // <0=> Read: 1 cycle / Write: 2 cycles // <1=> Read: 2 cycle / Write: 3 cycles // <2=> Read: 3 cycle / Write: 4 cycles // <3=> Read: 4 cycle / Write: 4 cycles // */ .equ EFC_SETUP, 1 .equ EFC_FMR_Val, 0x00320100 // Watchdog Timer (WDT) definitions .equ WDT_BASE, 0xFFFFFD40 /* WDT Base Address */ .equ WDT_MR, 0x04 /* WDT_MR Offset */ /* // Watchdog Timer (WDT) // WDV: Watchdog Counter Value <0-4095> // WDD: Watchdog Delta Value <0-4095> // WDFIEN: Watchdog Fault Interrupt Enable // WDRSTEN: Watchdog Reset Enable // WDRPROC: Watchdog Reset Processor // WDDBGHLT: Watchdog Debug Halt // WDIDLEHLT: Watchdog Idle Halt // WDDIS: Watchdog Disable // */ .equ WDT_SETUP, 1 .equ WDT_MR_Val, 0x00008000 // Power Mangement Controller (PMC) definitions .equ PMC_BASE, 0xFFFFFC00 /* PMC Base Address */ .equ PMC_MOR, 0x20 /* PMC_MOR Offset */ .equ PMC_MCFR, 0x24 /* PMC_MCFR Offset */ .equ PMC_PLLR, 0x2C /* PMC_PLLR Offset */ .equ PMC_MCKR, 0x30 /* PMC_MCKR Offset */ .equ PMC_SR, 0x68 /* PMC_SR Offset */ .equ PMC_MOSCEN, (1<<0) /* Main Oscillator Enable */ .equ PMC_OSCBYPASS, (1<<1) /* Main Oscillator Bypass */ .equ PMC_OSCOUNT, (0xFF<<8) /* Main OScillator Start-up Time */ .equ PMC_DIV, (0xFF<<0) /* PLL Divider */ .equ PMC_PLLCOUNT, (0x3F<<8) /* PLL Lock Counter */ .equ PMC_OUT, (0x03<<14) /* PLL Clock Frequency Range */ .equ PMC_MUL, (0x7FF<<16) /* PLL Multiplier */ .equ PMC_USBDIV, (0x03<<28) /* USB Clock Divider */ .equ PMC_CSS, (3<<0) /* Clock Source Selection */ .equ PMC_PRES, (7<<2) /* Prescaler Selection */ .equ PMC_MOSCS, (1<<0) /* Main Oscillator Stable */ .equ PMC_LOCK, (1<<2) /* PLL Lock Status */ /* // Power Mangement Controller (PMC) // Main Oscillator // MOSCEN: Main Oscillator Enable // OSCBYPASS: Oscillator Bypass // OSCCOUNT: Main Oscillator Startup Time <0-255> // // Phase Locked Loop (PLL) // DIV: PLL Divider <0-255> // MUL: PLL Multiplier <0-2047> // PLL Output is multiplied by MUL+1 // OUT: PLL Clock Frequency Range // <0=> 80..160MHz <1=> Reserved // <2=> 150..220MHz <3=> Reserved // PLLCOUNT: PLL Lock Counter <0-63> // USBDIV: USB Clock Divider // <0=> None <1=> 2 <2=> 4 <3=> Reserved // // CSS: Clock Source Selection // <0=> Slow Clock // <1=> Main Clock // <2=> Reserved // <3=> PLL Clock // PRES: Prescaler // <0=> None // <1=> Clock / 2 <2=> Clock / 4 // <3=> Clock / 8 <4=> Clock / 16 // <5=> Clock / 32 <6=> Clock / 64 // <7=> Reserved // */ .equ PMC_SETUP, 1 .equ PMC_MOR_Val, 0x00000601 .equ PMC_PLLR_Val, 0x00481C0e // .equ PMC_PLLR_Val, 0x00419C05 .equ PMC_MCKR_Val, 0x00000007 #if defined(VECTORS_IN_RAM) && defined(ROM_RUN) /* Exception Vectors to be placed in RAM - added by mt -> will be used after remapping in ROM_RUN -> not needed for RAM_RUN Mapped to Address 0 after remapping in ROM_RUN Absolute addressing mode must be used. Dummy Handlers are implemented as infinite loops which can be modified. VECTORS_IN_RAM defined in makefile/by commandline */ .text .arm .section .vectram, "ax" VectorsRAM: LDR PC,Reset_AddrR // B Reset_Handler LDR PC,Undef_AddrR LDR PC,SWI_AddrR LDR PC,PAbt_AddrR LDR PC,DAbt_AddrR NOP /* Reserved Vector */ LDR PC,[PC,#-0xF20] /* Vector From AIC_IVR */ LDR PC,[PC,#-0xF20] /* Vector From AIC_FVR */ Reset_AddrR: .word Reset_Handler Undef_AddrR: .word Undef_HandlerR SWI_AddrR: .word SWI_HandlerR PAbt_AddrR: .word PAbt_HandlerR DAbt_AddrR: .word DAbt_HandlerR // .word 0xdeadbeef /* Test Reserved Address */ .word 0 /* Reserved Address */ IRQ_AddrR: .word IRQ_HandlerR FIQ_AddrR: .word FIQ_HandlerR Undef_HandlerR: B Undef_HandlerR SWI_HandlerR: B SWI_HandlerR PAbt_HandlerR: B PAbt_HandlerR DAbt_HandlerR: B DAbt_HandlerR IRQ_HandlerR: B IRQ_HandlerR FIQ_HandlerR: B FIQ_HandlerR #endif /* VECTORS_IN_RAM && ROM_RUN */ /* Exception Vectors - for ROM_RUN: placed in 0x00000000 - for RAM_RUN: placed at 0x00200000 (on AT91SAM7S64) -> will be used during startup before remapping with target ROM_RUN -> will be used "always" in code without remapping or with target RAM_RUN Mapped to Address relative address 0 of .text Absolute addressing mode must be used. Dummy Handlers are implemented as infinite loops which can be modified. */ .text .arm .section .vectrom, "ax" Vectors: LDR PC,Reset_Addr // B Reset_Handler LDR PC,Undef_Addr LDR PC,SWI_Addr LDR PC,PAbt_Addr LDR PC,DAbt_Addr NOP /* Reserved Vector */ // LDR PC,IRQ_Addr LDR PC,[PC,#-0xF20] /* Vector From AIC_IVR */ // LDR PC,FIQ_Addr LDR PC,[PC,#-0xF20] /* Vector From AIC_FVR */ Reset_Addr: .word Reset_Handler Undef_Addr: .word Undef_Handler SWI_Addr: .word SWI_Handler PAbt_Addr: .word PAbt_Handler DAbt_Addr: .word DAbt_Handler .word 0 /* Reserved Address */ IRQ_Addr: .word IRQ_Handler FIQ_Addr: .word FIQ_Handler Undef_Handler: B Undef_Handler SWI_Handler: B SWI_Handler PAbt_Handler: B PAbt_Handler DAbt_Handler: B DAbt_Handler IRQ_Handler: B IRQ_Handler FIQ_Handler: B FIQ_Handler // "eddie's variables and constants - space reserved in flash to mirror ram. .equ DSTCK, Top_Stack - 0X400 .equ RAMoffset,0x100000 // buffers .equ tobsize, 128 .equ tibsize, 128 .equ padsize, 128 RESTIB: .skip tibsize // text input buffer .equ TIB, RESTIB+RAMoffset RESTOB: .skip tobsize // text ouptut buffer .equ TOB, RESTOB+RAMoffset RESPAD: .skip padsize // PAD buffer .equ PAD, RESPAD+RAMoffset // byte variables RESINPTR: .skip 1 .equ INPTR, RESINPTR+RAMoffset RESOUTPTR: .skip 1 .equ OUTPTR, RESOUTPTR+RAMoffset .align // word variables. RESDP: .word _etext+0X80+(RAM_BASE-FLASH_BASE) .equ VARDP, RESDP+RAMoffset RESCONTEXT: .word lastword .equ VARCONTEXT, RESCONTEXT+RAMoffset //' existing startup code // Starupt Code must be linked first at Address at which it expects to run. .text .arm .section .init, "ax" .global _startup .func _startup _startup: // Reset Handler LDR pc, =Reset_Handler Reset_Handler: // Setup EFC .if EFC_SETUP LDR R0, =EFC_BASE LDR R1, =EFC_FMR_Val STR R1, [R0, #EFC_FMR] .endif // Setup WDT .if WDT_SETUP LDR R0, =WDT_BASE LDR R1, =WDT_MR_Val STR R1, [R0, #WDT_MR] .endif // Setup PMC .if PMC_SETUP LDR R0, =PMC_BASE // Setup Main Oscillator LDR R1, =PMC_MOR_Val STR R1, [R0, #PMC_MOR] // Wait until Main Oscillator is stablilized .if (PMC_MOR_Val & PMC_MOSCEN) MOSCS_Loop: LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_MOSCS BEQ MOSCS_Loop .endif // Setup the PLL .if (PMC_PLLR_Val & PMC_MUL) LDR R1, =PMC_PLLR_Val STR R1, [R0, #PMC_PLLR] // Wait until PLL is stabilized PLL_Loop: LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_LOCK BEQ PLL_Loop .endif // Select Clock LDR R1, =PMC_MCKR_Val STR R1, [R0, #PMC_MCKR] .endif // Setup Stack for each mode LDR R0, =Top_Stack // Enter Undefined Instruction Mode and set its Stack Pointer MSR CPSR_c, #Mode_UND|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #UND_Stack_Size // Enter Abort Mode and set its Stack Pointer MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #ABT_Stack_Size // Enter FIQ Mode and set its Stack Pointer MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #FIQ_Stack_Size // Enter IRQ Mode and set its Stack Pointer MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #IRQ_Stack_Size // Enter Supervisor Mode and set its Stack Pointer MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #SVC_Stack_Size // Enter User Mode and set its Stack Pointer MSR CPSR_c, #Mode_USR MOV SP, R0 // Setup a default Stack Limit (when compiled with "-mapcs-stack-check") SUB SL, SP, #USR_Stack_Size /* #ifdef ROM_RUN // Relocate .data section (Copy from ROM to RAM) LDR R1, =_etext // 001008d0 A _etext LDR R2, =_data // 00200000 D _data LDR R3, =_edata // 00200058 A _edata LoopRel: CMP R2, R3 LDRLO R0, [R1], #4 STRLO R0, [R2], #4 BLO LoopRel #endif // Clear .bss section (Zero init) MOV R0, #0 LDR R1, =__bss_start__ LDR R2, =__bss_end__ LoopZI: CMP R1, R2 STRLO R0, [R1], #4 BLO LoopZI */ #if defined(VECTORS_IN_RAM) || defined(RAM_RUN) /* *** Remap *** ROM_RUN: exception vectors for RAM have been already copied to 0x00200000 by the .data copy-loop RAM_RUN: exception vectors are already placed at 0x0020000 by linker settings */ .equ MC_BASE,0xFFFFFF00 /* MC Base Address */ .equ MC_RCR, 0x00 /* MC_RCR Offset */ LDR R0, =MC_BASE MOV R1, #1 STR R1, [R0, #MC_RCR] // Remap #endif /* VECTORS_IN_RAM || RAM_RUN */ // "eddie's code starts here. // Relocate Flash to RAM section (Copy from ROM to RAM) LDR R1, = FLASH_BASE LDR R2, = RAM_BASE // 00200000 D _data LDR R3, = DSTCK // LoopRel: CMP R2, R3 LDRLO R0, [R1], #4 STRLO R0, [R2], #4 BLO LoopRel // ldr r0,=RAM_BASE-FLASH_BASE // add pc,r0 // start executing in RAM .macro ResetDstack ldr r7,=DSTCK .endm .macro plus1 add r6,#1 // add one to top .endm .macro plus2 add r6,#2 // add one to top .endm .macro sub1 sub r6,#1 // sub 1 .endm .macro sub2 sub r6,#2 // sub 2 .endm .macro div2 lsr r6,#1 // div 2 .endm .macro mul2 lsl r6,#1 // mul 2 .endm .macro Top2R0 // top to ro, without poping stack. mov r0,r6 .endm .macro AT ldr r6,[r6] .endm .macro CAT ldrb r6,[r6] .endm // ========== Register definition for PMC peripheral ========== .equ PMC_PCER, 0xFFFFFC10 // (PMC) Peripheral Clock Enable Register .equ ID_PIOA, 2 // Parallel IO Controller bit .equ ID_US0, 6 // USART 0 .equ ID_US1, 7 // USART 0 // enable the clock of the PIO (mt:) and UART0 // AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, ( 1 << AT91C_ID_PIOA ) | ( 1 << AT91C_ID_US0 ) ) ; // IO Controller definitions .equ PIO_PER, 0xFFFFF400 // (PIOA) PIO Enable Register .equ PIO_OER, 0xFFFFF410 // (PIOA) Output Enable Register .equ PIO_CODR,0xFFFFF434 // (PIOA) Clear Output Data Register .equ PIO_SODR,0xFFFFF430 // (PIOA) Set Output Data Register // ========== Register definition for PIOA peripheral ========== .equ PIOA_PDR, 0xFFFFF404 // (PIOA) PIO Disable Register // ========== Register definition for usart peripheral ========== .equ US_RSTRX, 1 << 2 // (DBGU) Reset Receiver .equ US_RSTTX, 1 << 3 // (DBGU) Reset Transmitter .equ US_RXEN, 1 << 4 // (DBGU) Receiver Enable .equ US_RXDIS, 1 << 5 // (DBGU) Receiver Disable .equ US_TXEN, 1 << 6 // (DBGU) Transmitter Enable .equ US_TXDIS, 1 << 7 // (DBGU) Transmitter Disable .equ RSTSTA, 1 << 8 // (DBGU) Reset Status Bits .equ PA5_RXD0, 1 << 5 .equ PA6_TXD0, 1 << 6 .equ PA21_RXD1, 1 << 21 .equ PA22_TXD1, 1 << 22 .equ BASE_US0, 0xFFFC0000 // (US0) Base Address .equ BASE_US1, 0xFFFC4000 // (US1) Base Address .equ US_MR, 0x4 .equ US_CSR, 0x14 .equ US_RHR, 0x18 .equ US_THR, 0x1C .equ US_BRGR, 0x20 .equ US_USMODE_NORMAL, 0x0 // (USART) Normal .equ US_CLKS_CLOCK, 0x0 << 4 // (USART) Clock .equ US_NBSTOP_1_BIT, 0x0 << 12 // (USART) 1 stop bit .equ US_PAR_NONE, 0x4 << 9 // (DBGU) No Parity .equ US_CHRL_8_BITS, 0x3 << 6 // (USART) Character Length: 8 bit .equ US_RXRDY, 0x1 << 0 // (DBGU) RXRDY Interrupt .equ US_TXRDY, 0x1 << 1 // (DBGU) TXRDY Interrupt // Enable RxD0 Pin Enable TxD0 Pin */ LDR R0, =PIOA_PDR LDR R1, =PA5_RXD0|PA6_TXD0|PA21_RXD1|PA22_TXD1 STR R1, [R0] /* // set up usart 0 // Reset Receiver Reset Transmitter Receiver Disable Transmitter Disable LDR R0, =BASE_US0 // same as US_CR MOV R1, #US_RSTRX|US_RSTTX|US_RXDIS|US_TXDIS; STR R1, [R0] // Normal Mode Clock = MCK No Parity 1 Stop Bit MOV R1, #US_USMODE_NORMAL|US_CLKS_CLOCK|US_CHRL_8_BITS|US_PAR_NONE|US_NBSTOP_1_BIT; STR R1, [R0,#US_MR] // Baud Rate Divisor 38.4Kbd with 48mhz clock = 78 MOV R1, #78; STR R1, [R0,#US_BRGR] // Receiver Enable Transmitter Enable MOV R1, #US_RXEN|US_TXEN; STR R1, [R0] */ // set up usart 1 // Reset Receiver Reset Transmitter Receiver Disable Transmitter Disable LDR R0, =BASE_US1 // same as US_CR MOV R1, #US_RSTRX|US_RSTTX|US_RXDIS|US_TXDIS; STR R1, [R0] // Normal Mode Clock = MCK No Parity 1 Stop Bit MOV R1, #US_USMODE_NORMAL|US_CLKS_CLOCK|US_CHRL_8_BITS|US_PAR_NONE|US_NBSTOP_1_BIT; STR R1, [R0,#US_MR] // Baud Rate Divisor 38.4Kbd with 48mhz clock = 78 MOV R1, #78; STR R1, [R0,#US_BRGR] // Receiver Enable Transmitter Enable MOV R1, #US_RXEN|US_TXEN; STR R1, [R0] // p_pPMC->PMC_PCER = 1 << AT91C_ID_PIOA; LDR R0, =PMC_PCER MOV R1, #1<PIO_PER = BIT8; //Enable PA8 LDR R0, =PIO_PER MOV R1, #1<<8 STR R1, [R0] // p_pPio->PIO_OER = BIT8; //Configure in Output STR R1, [R0,#(PIO_OER-PIO_PER)] .equ base_RSTC, 0xFFFFFD00 .equ RSTC_MR, 0x8 .equ RSTC_URSTEN, 1 //*AT91C_RSTC_RMR = (0xA5000000|AT91C_RSTC_URSTEN); LDR R0, =base_RSTC+RSTC_MR ldr R1, =0xA5000000|RSTC_URSTEN STR R1, [R0] ResetDstack //' Switch to thumb mode add R1,PC,#1 //;Load address of SUB_BRANCH, Set for THUMB by adding 1 BX R1 //;R1 contains address of SUB_BRANCH+1 //;Assembler-specific instruction to switch to Thumb .thumb SUB_BRANCH: teststart: // BL RTliteral // .align // .word _etext+0X80+(RAM_BASE-FLASH_BASE) // BL RTliteral // .align // .word VARDP // BL store // // BL RTliteral // .align // .word lastword // BL RTliteral // .align // .word VARCONTEXT // BL store // BL RTSliteral .word 0 BL RTliteral .align .word OUTPTR bl Cstore ldr r4,=0x10 ledloop: bl flashled sub r4,r4, #1 //** bne ledloop LDR R0,=0X41 BL sout // b ledloop bl dotquote .byte 19 .ascii "SAM7 Thumb ekm 2006" .align 1 bl CR BL RTliteral .align .word RAM_BASE-FLASH_BASE bl DpopR0 add PC,r0 mov r0,pc bl DpushR0 bl dothex32 bl CR bl VLIST mov r0,pc bl DpushR0 bl dothex32 bl CR B QUIT //'************************************************************************ //' Start of FORTH dictionary //( LINK , FLAGS , CNT , NAME , BODY/POINTER ) //( 32bit(aligned), BYTE, BYTE, ?BYTES, 32bit (aligned) ) //4 CONSTANT F_REMT ( remote flag ie headerless code or alias ) .equ F_REMT, 4 .equ F_THUMB, 0x20 dictionary: .align CRHead: .word 0 // null link at beginning of dic. .byte F_REMT|F_THUMB // flags .byte 2 .ascii "CR" .align .word CR+RAMoffset // Code field DUPHead: .word CRHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 3 .ascii "DUP" .align .word DUP+RAMoffset // Code field SWAPHead: .word DUPHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "SWAP" .align .word SWAP+RAMoffset // Code field OVERHead: .word SWAPHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "OVER" .align .word OVER+RAMoffset // Code field DROPHead: .word OVERHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "DROP" .align .word DROP+RAMoffset // Code field storeHead: .word DROPHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "!" .align .word store+RAMoffset // Code field CstoreHead: .word storeHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 2 .ascii "C!" .align .word Cstore+RAMoffset // Code field commaHead: .word CstoreHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "," .align .word comma+RAMoffset // Code field CcommaHead: .word commaHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 2 .ascii "C," .align .word Ccomma+RAMoffset // Code field HcommaHead: .word CcommaHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 2 .ascii "H," .align .word Hcomma+RAMoffset // Code field addHead: .word HcommaHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "+" .align .word add+RAMoffset // Code field subHead: .word addHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "-" .align .word sub+RAMoffset // Code field ANDHead: .word subHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 3 .ascii "AND" .align .word AND+RAMoffset SPACEHead: .word ANDHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 5 .ascii "SPACE" .align .word SPACE+RAMoffset // Code field EMITHead: .word SPACEHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "EMIT" .align .word EMIT+RAMoffset // Code field TYPEHead: .word EMITHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "TYPE" .align .word TYPE+RAMoffset // Code field ATHead: .word TYPEHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "@" .align .word Iat+RAMoffset // Code field CATHead: .word ATHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 2 .ascii "C@" .align .word Icat+RAMoffset // Code field DOTHead: .word CATHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "." .align .word dothex32+RAMoffset // Code field WORDHead: .word DOTHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "WORD" .align .word WORD+RAMoffset // Code field CONTEXTHead: .word WORDHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 7 .ascii "CONTEXT" .align .word CONTEXT+RAMoffset // Code field DUMPHead: .word CONTEXTHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "DUMP" .align .word DUMP+RAMoffset // Code field SPstorehead: .word DUMPHead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 3 .ascii "SP!" .align .word SPstore+RAMoffset // Code field dotShead: .word SPstorehead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 2 .ascii ".S" .align .word dotS+RAMoffset // Code field DPhead: .word dotShead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 2 .ascii "DP" .align .WORD DP+RAMoffset // Code field tickhead: .word DPhead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "'" .align .word tick+RAMoffset // Code field cfahead: .word tickhead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 6 .ascii "LFA>CA" .align .word lfa2ca+RAMoffset // Code field commenthead: .word cfahead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 1 .ascii "(" .align .word comment+RAMoffset // Code field swapdrophead: .word commenthead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 8 .ascii "SWAPDROP" .align .word DROPNXT+RAMoffset // same as swap drop DpopR0head: .word swapdrophead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "T>R0" // Name field .align .word DpopR0+RAMoffset // pop top to ro, pop dstack into top DpopR0R1head: .word DpopR0head+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 7 .ascii "TN>R0R1" .align .word DpopR0R1+RAMoffset // pop top and next to r0,r1 DpushR0head: .word DpopR0R1head+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "R0>T" .align .word DpushR0+RAMoffset // push ro to top, top onto dstack slithead: .word DpushR0head+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 6 .ascii "[SLIT]" .align .word RTSliteral+RAMoffset // push short literal stack lithead: .word slithead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 5 .ascii "[LIT]" .align .word RTliteral+RAMoffset // push LIT to stack EXECUTEhead: .word lithead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 7 .ascii "EXECUTE" .align .word EXECUTE+RAMoffset // EXECUTE address at top NUMBERhead: .word EXECUTEhead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 6 .ascii "NUMBER" .align .word NUMBER+RAMoffset // EXECUTE address at top GETLINEhead: .word NUMBERhead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 7 .ascii "GETLINE" .align .word GETLINE+RAMoffset // EXECUTE address at top FINDhead: .word GETLINEhead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 4 .ascii "FIND" .align .word FIND+RAMoffset // EXECUTE address at top printhead: .word FINDhead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 3 .ascii "[.]" .align .word dotquote+RAMoffset // EXECUTE address at top VLISTHead: .word printhead+RAMoffset // Link Field .byte F_REMT|F_THUMB // flags .byte 5 .ascii "VLIST" .align .word VLIST+RAMoffset // Code field .equ lastword, VLISTHead+RAMoffset DUMP: // addr len -- MT ; hex dump memory push {lr} BL DpopR0R1 // len/top in R0, addr/next in R1 mov r3,r0 // mov len to r3. dumpline: mov r0,r1 // copy addr to r0 bl DpushR0 // push addr for printing bl CR bl dothex32 ldr r4,=0x10 // load byte counter. dumpbyte: sub r3,#1 bmi enddump ldrb r0,[r1] add r1,#1 bl DpushR0 // push addr for printing bl dothex8 sub r4,#1 beq dumpline b dumpbyte enddump: bl CR pop {pc} //-------------------------------------------------------------------------- VLIST: push {lr} bl CONTEXT // get the link to vocab onto top. loopVL: AT // @ it to get the address of the first word bl DUP bl dothex32 cmp r6,#0 // check for zero - ie end of list beq endvlist bl DUP // copy link add r6,#5 // advance to word Cstring bl TYPE // type it out bl CR // new line b loopVL // loop back endvlist: bl DROP // drop zero (use ?dup in forth version. pop {pc} //-------------------------------------------------------------------------- store: push {lr} bl DpopR0R1 // get top and next str r1,[r0] pop {pc} //-------------------------------------------------------------------------- Cstore: push {lr} bl DpopR0R1 // get top and next strb r1,[r0] pop {pc} //-------------------------------------------------------------------------- DUP: // duplicate top. str r5,[r7] add r7,#4 mov r5,r6 mov pc,lr //-------------------------------------------------------------------------- SWAP: push {r6,lr} mov r6,r5 pop {r5,pc} //-------------------------------------------------------------------------- OVER: mov r0,r5 // T N --> N T N DpushR0: // push ro to top, top onto dstack str r5,[r7] add r7,#4 mov r5,r6 mov r6,r0 mov pc,lr //-------------------------------------------------------------------------- DpopR0R1:// pop top and next to r0,r1 mov r0,r6 mov r1,r5 sub r7,#8 ldr r5,[r7] ldr r6,[r7,#4] mov pc,lr //-------------------------------------------------------------------------- DpopR0: // pop top to ro, pop dstack into top mov r0,r6 DROP: mov r6,r5 // drop top. DROPNXT: sub r7,#4 // same as swap drop. ldr r5,[r7] mov pc,lr //-------------------------------------------------------------------------- AND: // add top and next adjust stack and r6,r5 b DROPNXT //-------------------------------------------------------------------------- add: // add top and next adjust stack add r6,r5 b DROPNXT //-------------------------------------------------------------------------- sub: // SUB top from next adjust stack sub r6,r5,r6 b DROPNXT //-------------------------------------------------------------------------- SPACE: push {lr} // emit one space to TOB ldr r0,=0x20 bl emitr0 pop {pc} //-------------------------------------------------------------------------- EMIT: push {lr} bl DpopR0 bl emitr0 pop {pc} //-------------------------------------------------------------------------- dotquote: // forth style text output, sout for now buffered later. // link reg points to count byte mov r1,lr // copy lr because lr will be needed for bl sub r1,#1 // in thumb mode lsb is set.. ldrb r2,[r1] // get the count to r2 charoutloop: add r1, #1 ldrb r0,[r1] // get the chr to r0 bl emitr0 //bl sout sub r2,#1 bne charoutloop add r1,#2 // align to word boundary ldr r0,=1 // lsb high for thumb orr r1,r0 mov pc,r1 sout: // send char in r0 to serial (uart one) push {R1,R2,r3,LR} LDR R1, =BASE_US1 // load base address to usart one. wait4tx1rdy: LDR r2,[R1,#US_CSR] // wait for ready to send ldr r3,=US_TXRDY AND R2, R3 BEQ wait4tx1rdy STRB R0, [R1,#US_THR] pop {R1,R2,r3,PC} sin: // return serial char in r0 (uart one) push {R1,R2,LR} LDR R1, =BASE_US1 // load base address to usart one. wait4rx: LDR r2,[R1,#US_CSR] // wait for char ldr r0,=US_RXRDY AND R2, R0 BEQ wait4rx LDRB r0,[R1,#US_RHR] pop {R1,R2,PC} delaysub: ldr r2,=0x80000 delay: sub r2,#1 bne delay mov pc,lr ledon: LDR R0, =PIO_CODR B doled ledoff: LDR R0, =PIO_SODR doled: push {R1,LR} ldr R1,=1<<8 STR R1, [R0] pop {R1,PC} flashled: push {LR} bl ledon bl delaysub bl ledoff bl delaysub pop {PC} tick: push {LR} // find word in dict. BL RTSliteral .word 0x20 // push space code. BL WORD CAT bl DpopR0 cmp r0,#0 beq tickerr bl FIND bl DpopR0 cmp r0,#0 beq tickerr pop {PC} tickerr: bl dotquote .byte 3 .ascii "???" .align 1 bl CR pop {pc} //-------------------------------------------------------------------------- NUMBER: push {lr} ldr r3,=PAD // -- false or True NUM ;only hex in this version. ldrb r2,[r3] // get len at PAD ldr r1,=0 // build number here. ldr r4,=1 // neg flag add r3,#1 // inc char pointer to first char. ldrb r0,[r3] // get char cmp r0,#0x2D bne noinc // not "-" ldr r4,=0 sub r2,#1 Numloop: add r3,#1 // inc char pointer. noinc: lsl r1,#4 ldrb r0,[r3] // get chars, left char first. sub r0,#0x30 // ie ascii for zero is hex 30. bmi badnum cmp r0,#9 // is is 0 to 9 ? ble addit sub r0,#7 // ascii A is 41 cmp r0,#0xf bgt badnum cmp r0,#0xa bmi badnum addit: add r1,r0 sub r2,#1 bgt Numloop cmp r4,#0 bne notneg sub r0,r4,r0 b pushnum notneg: mov r0,r1 pushnum: bl DpushR0 ldr r0,=1 bl DpushR0 pop {pc} badnum: ldr r0,=0 bl DpushR0 pop {pc} ////////////////////////////////////////////////////////// WORD: // delim -- padaddr push {lr} ldr r1,=INPTR ldrb R1,[R1] ldr r2,=TIB ldr r3,=PAD ldr r4,=0 // word len skiploop: ldrb r0,[r1,r2] // get char cmp r0,r6 // compare top to skip leading delim bne wordloop cmp r1,#tibsize bge lineend cmp r0,#0x20 bmi lineend // done when control char found add r1,#1 b skiploop wordloop: cmp r0,r6 // compare with top beq worddone // done when delim found cmp r0,#0x20 bmi lineend // done when control char found add r3,#1 // inc PADptr strb r0,[r3] // store char in pad add r4,#1 // inc word length add r1,#1 // inc inptr ldrb r0,[r1,r2] // get char b wordloop worddone: add r1,#1 lineend: ldr r3,=PAD strb r4,[r3] // set length ldr r4,=INPTR strb r1,[r4] // save inptr mov r6,r3 // replace top with PAD address // mov pc,lr pop {pc} //-------------------------------------------------------------------------- TYPE: // addr -- ; note cmforth left the next address at top. ans doesn't push {lr} bl DpopR0 mov r2,r0 // mov so emit can use r0 ldrb r1,[r2] // get count typeloop: sub r1,#1 bmi typedone add r2,#1 ldrb r0,[r2] // bl sout bl emitr0 b typeloop typedone: pop {pc} //-------------------------------------------------------------------------- lfa2ca: add r6,#4 // advance to flags ldrb r1,[r6] // get flags to r1 add r6,#1 // advance to word Cstring ldrb r0,[r6] // get length add r6,r0 // advance r6 to last char. ldr r0,=F_REMT and r1,r0 // check the remote flag. bne remoteCA // if set the code is remote. ldr r0,=1 // local - halfword align. orr r6,r0 add r6,#1 mov pc,lr remoteCA: ldr r0,=3 // Remote - word aligh and fetch orr r6,r0 add r6,#1 AT mov pc,lr //-------------------------------------------------------------------------- EXECUTE: push {lr} // we need to push lr for [CON] etc to work properly. bl DpopR0 add r0,#1 // lsb set for thumb mode, OR have odd address in dic. add r1,pc,#4 mov lr,r1 bx r0 add r0,#0 // a nop pop {pc} INTERPRET: push {lr} interloop: ldr r0,=0x20 bl DpushR0 bl WORD CAT bl DpopR0 cmp r0,#0 beq leaveinterp bl FIND bl DpopR0 cmp r0,#0 beq notfound bl lfa2ca // bl DpopR0 bl EXECUTE // BL flashled b interloop notfound: bl NUMBER bl DpopR0 cmp r0,#0 bne interloop ldr r0,=PAD bl DpushR0 bl TYPE bl dotquote .byte 3 .ascii " ??" .align 1 bl CR leaveinterp: pop {pc} GETLINE: push {lr} ldr r0,=0 // reset in text buffer pointer ldr r1,=INPTR strb R0,[R1] ldr r1,=TIB keygetloop: bl sin cmp r0,#0x9 // convert tabs to spaces bne notab ldr r0,=0x20 notab: strb r0,[r1] add r1,#1 cmp r0,#0xd bne keygetloop pop {pc} QUIT: bl GETLINE bl CR bl INTERPRET // DEPTH // 0 < IF ABORT" DATA STACK UNDERFLOW!!" THEN // ECHO @ IF ." ok " CR THEN // AGAIN //; // bl flashled bl SPACE bl dotquote .byte 2 .ascii "OK" .align 1 bl CR B QUIT Iat: // @ for interpreter AT mov pc,lr Icat: // C@ for interpreter CAT mov pc,lr emitr0: push {R1,R2,r3,LR} ldr r3,=OUTPTR // load address of out char pointer ldrb r2,[r3] // load the pointer cmps r2,#(tobsize) bge endemit ldr r1,=TOB strb r0,[r1,r2] add r2,r2,#1 strb r2,[r3] endemit: pop {R1,R2,r3,PC} CR: push {R1,R2,r3,LR} ldr r3,=OUTPTR // load address of out char pointer ldrb r2,[r3] // load the pointer ldr r1,=TOB // load the buffer address crloop: sub r2,#1 // dec the pointer - used as loop cnt bmi endcr // leave if zero ldrb r0,[r1] // get char from buffer, inc bufferptr add r1, #1 bl sout // send it b crloop // loop back endcr: ldr r0,=0xd // send cr lf bl sout ldr r0,=0xa bl sout ldrb r2,=0 // set char point to zero strb r2,[r3] pop {R1,R2,r3,PC} RTliteral: // get the word at LR to top and advance LR. mov r1,lr // we can't use LR with ldr so copy it add r1,#2 // LR/R1 will be odd in thumb ldr r2,=-4 // word align and r1,r2 ldr r0,[r1] add r1,#5 // adjust to next inst plus one. mov lr,r1 b DpushR0 RTSliteral: // get the word at LR to top and advance LR. mov r1,lr // we can't use LR with ldr so copy it ldr r2,=-2 // hword align and r1,r2 ldrh r0,[r1] add r1,#3 // adjust to next inst plus one. mov lr,r1 b DpushR0 //-------------------------------------------------------------------------- SPstore: // reset data stack ResetDstack mov pc,lr //-------------------------------------------------------------------------- comma: push {lr} bl DP // -- VAL DP bl SWAP // -- DP VAL bl OVER // -- DP VAL DP AT // -- DP VAL *DP add r6,#3 ldr r2,=-4 // word align and r6,r2 bl SWAP // -- DP *DP VAL bl OVER // -- DP *DP VAL *DP bl store // -- DP *DP add r6,#4 // -- DP Nextfree bl SWAP // -- NF DP bl store // -- pop {pc} Ccomma: push {lr} bl DP // -- VAL DP bl SWAP // -- DP VAL bl OVER // -- DP VAL DP AT // -- DP VAL *DP bl Cstore // -- DP bl DUP // -- DP DP AT // -- DP *DP add r6,#1 // -- DP Nextfree bl SWAP // -- NF DP bl store // -- pop {pc} Hcomma: push {lr} bl DP // -- VAL DP bl SWAP // -- DP VAL bl OVER // -- DP VAL DP AT // -- DP VAL *DP bl OVER bl OVER bl Cstore // -- DP add r6,#1 // -- DP Nextfree asr r5,#8 bl Cstore // -- DP bl DUP // -- DP DP AT // -- DP *DP add r6,#2 // -- DP Nextfree bl SWAP // -- NF DP bl store // -- pop {pc} comment: push {lr} // Scan for ) or end of line ldr r0,=0x29 bl DpushR0 bl WORD bl DpopR0 pop {pc} //-------------------------------------------------------------------------- FIND: push {lr} bl CONTEXT // get the link to vocab onto top. loopfind: AT // @ it to get the address of the first word cmp r6,#0 // check for zero - ie end of list beq endfind // if so word was not found. add R4,r6,#5 // advance to word Cstring // now compare PAD with word. ldr r3,=PAD ldrb r1,[r4] // get dic word count to r1 ldrb r0,[r3] // get len at PAD cmp r0,r1 // compare length bne loopfind // not equal try next word. wrdcmplp: ldrb r0,[r4,r1] // r1 = count. ldrb r2,[r3,r1] cmp r0,r2 bne loopfind // not equal try next word. sub r1,#1 beq foundit b wrdcmplp // loop back foundit: ldr r0,=1 bl DpushR0 // push true flag onto stack. endfind: pop {pc} // top has true+LFA or false CONTEXT: ldr r0,=VARCONTEXT b DpushR0 DP: ldr r0,=VARDP b DpushR0 //' debuging code which will be removed from finished kernel. pushhex: push {r1,lr} ldr r1,=0xf and r0,r1 cmp r0,#9 ble underA add r0,#7 underA: add r0,#0x30 bl DpushR0 pop {r1,pc} dothexN: PUSH {R1} mov r2,r6 bl DpopR0 dohexdigit: mov r0,r2 bl pushhex lsr r2,r2,#4 sub r1,#1 bne dohexdigit POP {r1} hexout: bl EMIT sub r1,#1 bne hexout bl SPACE pop {R1,R2,pc} dothex8:// print top as 2 hex digits push {r1,R2,lr} ldr r1,=2 b dothexN dothex32:// print top as 8 hex digits push {r1,R2,lr} ldr r1,=8 b dothexN //-------------------------------------------------------------------------- dotS: push {lr} ldr r1,=DSTCK cmp R1,R7 bge leavedots mov r0,r6 bl DpushR0 bl dothex32 bl CR add r1,#4 cmp R1,R7 bge leavedots mov r0,r5 bl DpushR0 bl dothex32 bl CR mov r1,R7 dotSloop: sub r1,#4 ldr r0,=DSTCK+4 cmp R1,r0 ble leavedots ldr r0,[r1] bl DpushR0 bl dothex32 bl CR b dotSloop leavedots: pop {pc} B leavedots mov r0,lr self: b self .arm