| 1 |
61 |
csantifort |
/*----------------------------------------------------------------
|
| 2 |
|
|
// //
|
| 3 |
|
|
// start.S //
|
| 4 |
|
|
// //
|
| 5 |
|
|
// This file is part of the Amber project //
|
| 6 |
|
|
// http://www.opencores.org/project,amber //
|
| 7 |
|
|
// //
|
| 8 |
|
|
// Description //
|
| 9 |
|
|
// Assembly routines for boot-loader. //
|
| 10 |
|
|
// As boot-loader is a stand-alone application, it needs a //
|
| 11 |
|
|
// simple start function written in assembly to call the //
|
| 12 |
|
|
// C code main() function. //
|
| 13 |
|
|
// //
|
| 14 |
|
|
// Author(s): //
|
| 15 |
|
|
// - Conor Santifort, csantifort.amber@gmail.com //
|
| 16 |
|
|
// //
|
| 17 |
|
|
//////////////////////////////////////////////////////////////////
|
| 18 |
|
|
// //
|
| 19 |
|
|
// Copyright (C) 2010 Authors and OPENCORES.ORG //
|
| 20 |
|
|
// //
|
| 21 |
|
|
// This source file may be used and distributed without //
|
| 22 |
|
|
// restriction provided that this copyright statement is not //
|
| 23 |
|
|
// removed from the file and that any derivative work contains //
|
| 24 |
|
|
// the original copyright notice and the associated disclaimer. //
|
| 25 |
|
|
// //
|
| 26 |
|
|
// This source file is free software; you can redistribute it //
|
| 27 |
|
|
// and/or modify it under the terms of the GNU Lesser General //
|
| 28 |
|
|
// Public License as published by the Free Software Foundation; //
|
| 29 |
|
|
// either version 2.1 of the License, or (at your option) any //
|
| 30 |
|
|
// later version. //
|
| 31 |
|
|
// //
|
| 32 |
|
|
// This source is distributed in the hope that it will be //
|
| 33 |
|
|
// useful, but WITHOUT ANY WARRANTY; without even the implied //
|
| 34 |
|
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
|
| 35 |
|
|
// PURPOSE. See the GNU Lesser General Public License for more //
|
| 36 |
|
|
// details. //
|
| 37 |
|
|
// //
|
| 38 |
|
|
// You should have received a copy of the GNU Lesser General //
|
| 39 |
|
|
// Public License along with this source; if not, download it //
|
| 40 |
|
|
// from http://www.opencores.org/lgpl.shtml //
|
| 41 |
|
|
// //
|
| 42 |
|
|
----------------------------------------------------------------*/
|
| 43 |
|
|
|
| 44 |
|
|
#include "amber_registers.h"
|
| 45 |
|
|
#include "address_map.h"
|
| 46 |
|
|
|
| 47 |
|
|
/* Defined in vmlinux/include/asm-arm/setup.h */
|
| 48 |
|
|
#define ATAG_CORE 0x54410001
|
| 49 |
|
|
#define ATAG_MEM 0x54410002
|
| 50 |
|
|
#define ATAG_INITRD 0x54410005
|
| 51 |
|
|
#define ATAG_RAMDISK 0x54410004
|
| 52 |
|
|
#define ATAG_NONE 0x00000000
|
| 53 |
|
|
|
| 54 |
|
|
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
|
| 55 |
|
|
#define ATAG_MEM_SIZE ((2*4 + 2*4) >> 2)
|
| 56 |
|
|
#define ATAG_INITRD_SIZE ((2*4 + 2*4) >> 2)
|
| 57 |
|
|
#define ATAG_RAMDISK_SIZE ((2*4 + 3*4) >> 2)
|
| 58 |
|
|
|
| 59 |
|
|
|
| 60 |
|
|
/* from vmlinux/arch/arm/kernel/compat.c */
|
| 61 |
|
|
#define FLAG_READONLY 1
|
| 62 |
|
|
|
| 63 |
|
|
/* from the list in wmlinux/arch/arm/tools/mach-types */
|
| 64 |
|
|
#define MACH_TYPE_A5K 11
|
| 65 |
|
|
|
| 66 |
|
|
|
| 67 |
|
|
|
| 68 |
|
|
.section .text
|
| 69 |
|
|
.globl start
|
| 70 |
|
|
start:
|
| 71 |
|
|
/* 0x00 Reset Interrupt vector address */
|
| 72 |
|
|
b startup
|
| 73 |
|
|
|
| 74 |
|
|
/* 0x04 Undefined Instruction Interrupt vector address */
|
| 75 |
|
|
b _testfail
|
| 76 |
|
|
|
| 77 |
|
|
/* 0x08 SWI Interrupt vector address */
|
| 78 |
|
|
b _testfail
|
| 79 |
|
|
|
| 80 |
|
|
/* 0x0c Prefetch abort Interrupt vector address */
|
| 81 |
|
|
b _testfail
|
| 82 |
|
|
|
| 83 |
|
|
/* 0x10 Data abort Interrupt vector address */
|
| 84 |
|
|
b _testfail
|
| 85 |
|
|
b _testfail
|
| 86 |
|
|
|
| 87 |
|
|
/* 0x18 IRQ vector address */
|
| 88 |
|
|
b service_irq
|
| 89 |
|
|
|
| 90 |
|
|
/* 0x1c FIRQ vector address */
|
| 91 |
|
|
b _testfail
|
| 92 |
|
|
|
| 93 |
|
|
|
| 94 |
|
|
.global _restart
|
| 95 |
|
|
_restart:
|
| 96 |
|
|
@ jump to address 0 in irq mode
|
| 97 |
|
|
mov pc, #0x00000002
|
| 98 |
|
|
nop
|
| 99 |
|
|
nop
|
| 100 |
|
|
nop
|
| 101 |
|
|
|
| 102 |
|
|
|
| 103 |
|
|
startup:
|
| 104 |
|
|
/* copy program to exec space */
|
| 105 |
|
|
mov r0, #0
|
| 106 |
|
|
ldr r1, AdrExecBase
|
| 107 |
|
|
1: ldm r0!, {r2-r9}
|
| 108 |
|
|
stm r1!, {r2-r9}
|
| 109 |
|
|
cmp r0, #0x4000
|
| 110 |
|
|
bne 1b
|
| 111 |
|
|
|
| 112 |
|
|
/* Fix the interrupt jump pointers */
|
| 113 |
|
|
ldr r0, AdrExecBase
|
| 114 |
|
|
mov r1, r0, lsr #2
|
| 115 |
|
|
mov r2, #0
|
| 116 |
|
|
|
| 117 |
|
|
2: ldr r3, [r2]
|
| 118 |
|
|
orr r3, r3, r1
|
| 119 |
|
|
str r3, [r2], #4
|
| 120 |
|
|
cmp r2, #0x1c
|
| 121 |
|
|
bne 2b
|
| 122 |
|
|
|
| 123 |
|
|
/* Jump to 2f but offset from ExecBase not current location */
|
| 124 |
|
|
3: ldr r0, AdrExecBase
|
| 125 |
|
|
ldr r1, AdrJumpPoint
|
| 126 |
|
|
orr r0, r0, r1
|
| 127 |
|
|
mov pc, r0
|
| 128 |
|
|
|
| 129 |
|
|
_jump_point:
|
| 130 |
|
|
|
| 131 |
|
|
/* Switch to IRQ Mode */
|
| 132 |
|
|
mov r0, #0x00000002
|
| 133 |
|
|
teqp pc, r0
|
| 134 |
|
|
/* Set IRQ Mode stack pointer */
|
| 135 |
|
|
ldr sp, AdrIRQStack
|
| 136 |
|
|
|
| 137 |
|
|
/* Switch to SVC mode and Unset interrupt mask bits */
|
| 138 |
|
|
mov r0, #0x00000003
|
| 139 |
|
|
teqp pc, r0
|
| 140 |
|
|
|
| 141 |
|
|
@ Enable the cache
|
| 142 |
|
|
@ set region 24 to be uncached. Used for packet buffers
|
| 143 |
|
|
mov r0, #0xfeffffff
|
| 144 |
|
|
mcr 15, 0, r0, cr3, cr0, 0 @ cacheable area
|
| 145 |
|
|
mov r0, #1
|
| 146 |
|
|
mcr 15, 0, r0, cr2, cr0, 0 @ cache enable
|
| 147 |
|
|
|
| 148 |
|
|
@ init SP
|
| 149 |
|
|
ldr sp, AdrStack
|
| 150 |
|
|
|
| 151 |
|
|
@ Set 32MB memory mode
|
| 152 |
|
|
ldr r0, AdrMemCtrl
|
| 153 |
|
|
mov r1, #1
|
| 154 |
|
|
str r1, [r0]
|
| 155 |
|
|
|
| 156 |
|
|
.extern main
|
| 157 |
|
|
bl main
|
| 158 |
|
|
|
| 159 |
|
|
@ jump to program at r0
|
| 160 |
|
|
.globl _jump_to_program
|
| 161 |
|
|
_jump_to_program:
|
| 162 |
|
|
|
| 163 |
|
|
|
| 164 |
|
|
@ ----------------------------------------------
|
| 165 |
|
|
@ Copy ATAG structure to AdrBootParams
|
| 166 |
|
|
@ ----------------------------------------------
|
| 167 |
|
|
ldr r1, AdrBootParams
|
| 168 |
|
|
ldr r2, AdrATAGBase
|
| 169 |
|
|
ldr r3, AdeEndATAG
|
| 170 |
|
|
|
| 171 |
|
|
1: cmp r2, r3
|
| 172 |
|
|
beq 2f
|
| 173 |
|
|
ldr r4, [r2], #4
|
| 174 |
|
|
str r4, [r1], #4
|
| 175 |
|
|
b 1b
|
| 176 |
|
|
|
| 177 |
|
|
@ Set memc page tables
|
| 178 |
|
|
2: ldr r2, AdrPageTabes
|
| 179 |
|
|
mov r3, #0
|
| 180 |
|
|
mov r4, #40
|
| 181 |
|
|
3: str r3,[r2],#4
|
| 182 |
|
|
subs r4, r4, #1
|
| 183 |
|
|
bne 3b
|
| 184 |
|
|
|
| 185 |
|
|
@ ----------------------------------------------
|
| 186 |
|
|
@ jump to start of program in svc mode with interrupts disabled
|
| 187 |
|
|
@ ----------------------------------------------
|
| 188 |
|
|
mov r4, r0
|
| 189 |
|
|
orr r4, #0x0c000003
|
| 190 |
|
|
mov r0, #0
|
| 191 |
|
|
mov pc, r4
|
| 192 |
|
|
|
| 193 |
|
|
|
| 194 |
|
|
service_irq:
|
| 195 |
|
|
@ Save all registers to the stack
|
| 196 |
|
|
stmfd sp!, {r0-r12, lr}
|
| 197 |
|
|
|
| 198 |
|
|
@ is it a timer interrupt ?
|
| 199 |
|
|
ldr r0, AdrInterruptStatus
|
| 200 |
|
|
ldr r1, [r0]
|
| 201 |
|
|
ands r2, r1, #0x20
|
| 202 |
|
|
beq 1f @ not timer int, jump
|
| 203 |
|
|
.extern timer_interrupt
|
| 204 |
|
|
bl timer_interrupt
|
| 205 |
|
|
|
| 206 |
|
|
@ is it an ethernet interrupt ?
|
| 207 |
|
|
1: ands r2, r1, #0x100
|
| 208 |
|
|
beq 2f @ not ethmac int, jump
|
| 209 |
|
|
.extern ethmac_interrupt
|
| 210 |
|
|
bl ethmac_interrupt
|
| 211 |
|
|
|
| 212 |
|
|
|
| 213 |
|
|
2: @ Restore all registers from the stack
|
| 214 |
|
|
ldmfd sp!, {r0-r12, lr}
|
| 215 |
|
|
|
| 216 |
|
|
@ Jump straight back to normal execution
|
| 217 |
|
|
subs pc, lr, #4
|
| 218 |
|
|
|
| 219 |
|
|
|
| 220 |
|
|
|
| 221 |
|
|
/* _testfail: Used to terminate execution in Verilog simulations */
|
| 222 |
|
|
/* On the board just puts the processor into an infinite loop */
|
| 223 |
|
|
.globl _testfail
|
| 224 |
|
|
_testfail:
|
| 225 |
|
|
ldr r11, AdrTestStatus
|
| 226 |
|
|
str r0, [r11]
|
| 227 |
|
|
b _testfail
|
| 228 |
|
|
|
| 229 |
|
|
|
| 230 |
|
|
/* _testpass: Used to terminate execution in Verilog simulations */
|
| 231 |
|
|
/* On the board just puts the processor into an infinite loop */
|
| 232 |
|
|
.globl _testpass
|
| 233 |
|
|
_testpass:
|
| 234 |
|
|
ldr r11, AdrTestStatus
|
| 235 |
|
|
mov r10, #17
|
| 236 |
|
|
str r10, [r11]
|
| 237 |
|
|
b _testpass
|
| 238 |
|
|
|
| 239 |
|
|
|
| 240 |
|
|
|
| 241 |
|
|
|
| 242 |
|
|
/* _div: Integer division function */
|
| 243 |
|
|
@ Divide r0 by r1
|
| 244 |
|
|
@ Answer returned in r1
|
| 245 |
|
|
.globl _div
|
| 246 |
|
|
.globl __aeabi_idiv
|
| 247 |
|
|
__aeabi_idiv:
|
| 248 |
|
|
_div:
|
| 249 |
|
|
stmdb sp!, {r4, lr}
|
| 250 |
|
|
|
| 251 |
|
|
@ set r4 to 1 if one of the two inputs is negative
|
| 252 |
|
|
and r2, r0, #0x80000000
|
| 253 |
|
|
and r3, r1, #0x80000000
|
| 254 |
|
|
eor r4, r2, r3
|
| 255 |
|
|
|
| 256 |
|
|
@ Invert negative numbers
|
| 257 |
|
|
tst r0, #0x80000000
|
| 258 |
|
|
mvnne r0, r0
|
| 259 |
|
|
addne r0, r0, #1
|
| 260 |
|
|
|
| 261 |
|
|
tst r1, #0x80000000
|
| 262 |
|
|
mvnne r1, r1
|
| 263 |
|
|
addne r1, r1, #1
|
| 264 |
|
|
|
| 265 |
|
|
@ divide r1 by r2, also use registers r0 and r4
|
| 266 |
|
|
mov r2, r1
|
| 267 |
|
|
mov r1, r0
|
| 268 |
|
|
|
| 269 |
|
|
cmp r2, #0
|
| 270 |
|
|
beq 3f
|
| 271 |
|
|
|
| 272 |
|
|
@ In order to divide r1 by r2, the first thing we need to do is to shift r2
|
| 273 |
|
|
@ left by the necessary number of places. The easiest method of doing this
|
| 274 |
|
|
@ is simply by trial and error - shift until we discover that r2 has become
|
| 275 |
|
|
@ too big, then stop.
|
| 276 |
|
|
mov r0,#0 @ clear r0 to accumulate result
|
| 277 |
|
|
mov r3,#1 @ set bit 0 in r3, which will be
|
| 278 |
|
|
@ shifted left then right
|
| 279 |
|
|
|
| 280 |
|
|
1: cmp r3, #0 @ escape on error
|
| 281 |
|
|
moveq r3, #0x10000000
|
| 282 |
|
|
beq 2f
|
| 283 |
|
|
cmp r2,r1
|
| 284 |
|
|
movls r2,r2,lsl#1
|
| 285 |
|
|
movls r3,r3,lsl#1
|
| 286 |
|
|
bls 1b
|
| 287 |
|
|
@ shift r2 left until it is about to be bigger than r1
|
| 288 |
|
|
@ shift r3 left in parallel in order to flag how far we have to go
|
| 289 |
|
|
|
| 290 |
|
|
@ r0 will be used to hold the result. The role of r3 is more complicated.
|
| 291 |
|
|
@ In effect, we are using r3 to mark where the right-hand end of r2 has got to
|
| 292 |
|
|
@ - if we shift r2 three places left, this will be indicated by a value of %1000
|
| 293 |
|
|
@ in r3. However, we also add it to r0 every time we manage a successful subtraction,
|
| 294 |
|
|
@ since it marks the position of the digit currently being calculated in the answer.
|
| 295 |
|
|
@ In the binary example (50 ÷ 10) above, we shifted the '10' two places left,
|
| 296 |
|
|
@ so at the time of the first subtraction, r3 would have been %100, at the time
|
| 297 |
|
|
@ of the second (which failed) it would have been %10, and at the time of the
|
| 298 |
|
|
@ third %1. Adding it to r0 after each successful subtraction would have
|
| 299 |
|
|
@ given us, once again, the answer of %101!
|
| 300 |
|
|
|
| 301 |
|
|
@ Now for the loop that actually does the work:
|
| 302 |
|
|
2: cmp r1,r2 @ carry set if r1>r2 (don't ask why)
|
| 303 |
|
|
subcs r1,r1,r2 @ subtract r2 from r1 if this would
|
| 304 |
|
|
@ give a positive answer
|
| 305 |
|
|
addcs r0,r0,r3 @ and add the current bit in r3 to
|
| 306 |
|
|
@ the accumulating answer in r0
|
| 307 |
|
|
|
| 308 |
|
|
@ In subtraction (a cmp instruction simulates a subtraction in
|
| 309 |
|
|
@ order to set the flags), if r1 - r2 gives a positive answer and no 'borrow'
|
| 310 |
|
|
@ is required, the carry flag is set. This is required in order to make SBC
|
| 311 |
|
|
@ (Subtract with Carry) work properly when used to carry out a 64-bit subtraction,
|
| 312 |
|
|
@ but it is confusing!
|
| 313 |
|
|
|
| 314 |
|
|
@ In this case, we are turning it to our advantage. The carry flag is set to
|
| 315 |
|
|
@ indicate that a successful subtraction is possible, i.e. one that doesn't
|
| 316 |
|
|
@ generate a negative result, and the two following instructions are carried
|
| 317 |
|
|
@ out only when the condition Carry Set applies. Note that the 'S' on the end
|
| 318 |
|
|
@ of these instructions is part of the 'CS' condition code and does not mean
|
| 319 |
|
|
@ that they set the flags!
|
| 320 |
|
|
|
| 321 |
|
|
movs r3,r3,lsr #1 @ Shift r3 right into carry flag
|
| 322 |
|
|
movcc r2,r2,lsr #1 @ and if bit 0 of r3 was zero, also
|
| 323 |
|
|
@ shift r2 right
|
| 324 |
|
|
bcc 2b @ If carry not clear, r3 has shifted
|
| 325 |
|
|
@ back to where it started, and we
|
| 326 |
|
|
@ can end
|
| 327 |
|
|
|
| 328 |
|
|
@ if one of the inputs is negetive then return a negative result
|
| 329 |
|
|
tst r4, #0x80000000
|
| 330 |
|
|
mvnne r0, r0
|
| 331 |
|
|
addne r0, r0, #1
|
| 332 |
|
|
3: ldmia sp!, {r4, pc}^
|
| 333 |
|
|
|
| 334 |
|
|
|
| 335 |
|
|
/* strcpy: String copy function
|
| 336 |
|
|
char * strcpy ( char * destination, const char * source );
|
| 337 |
|
|
destination is returned
|
| 338 |
|
|
*/
|
| 339 |
|
|
@ r0 points to destination
|
| 340 |
|
|
@ r1 points to source string which terminates with a 0
|
| 341 |
|
|
.globl strcpy
|
| 342 |
|
|
strcpy:
|
| 343 |
|
|
stmdb sp!, {r4-r6, lr}
|
| 344 |
|
|
@ Use r6 to process the destination pointer.
|
| 345 |
|
|
@ At the end of the function, r0 is returned, so need to preserve it
|
| 346 |
|
|
mov r6, r0
|
| 347 |
|
|
|
| 348 |
|
|
strcpy_main:
|
| 349 |
|
|
@ unroll the loop 4 times
|
| 350 |
|
|
ldrb r3, [r1], #1
|
| 351 |
|
|
strb r3, [r6], #1
|
| 352 |
|
|
cmp r3, #0
|
| 353 |
|
|
ldmeqia sp!, {r4-r6, pc}^
|
| 354 |
|
|
|
| 355 |
|
|
ldrb r3, [r1], #1
|
| 356 |
|
|
strb r3, [r6], #1
|
| 357 |
|
|
cmp r3, #0
|
| 358 |
|
|
ldmeqia sp!, {r4-r6, pc}^
|
| 359 |
|
|
|
| 360 |
|
|
ldrb r3, [r1], #1
|
| 361 |
|
|
strb r3, [r6], #1
|
| 362 |
|
|
cmp r3, #0
|
| 363 |
|
|
ldmeqia sp!, {r4-r6, pc}^
|
| 364 |
|
|
|
| 365 |
|
|
ldrb r3, [r1], #1
|
| 366 |
|
|
strb r3, [r6], #1
|
| 367 |
|
|
cmp r3, #0
|
| 368 |
|
|
ldmeqia sp!, {r4-r6, pc}^
|
| 369 |
|
|
|
| 370 |
|
|
b strcpy_main
|
| 371 |
|
|
|
| 372 |
|
|
|
| 373 |
|
|
|
| 374 |
|
|
/* strncpy: String copy function */
|
| 375 |
|
|
@ r0 points to destination
|
| 376 |
|
|
@ r1 points to source string
|
| 377 |
|
|
@ r2 is the number of bytes to copy
|
| 378 |
|
|
.globl strncpy
|
| 379 |
|
|
strncpy:
|
| 380 |
|
|
stmdb sp!, {r4, lr}
|
| 381 |
|
|
cmp r2, #0
|
| 382 |
|
|
beq 2f
|
| 383 |
|
|
add r4, r0, r2 @ set r4 to the address of the last byte copied
|
| 384 |
|
|
1: ldrb r3, [r1], #1
|
| 385 |
|
|
strb r3, [r0], #1
|
| 386 |
|
|
cmp r0, r4
|
| 387 |
|
|
bne 1b
|
| 388 |
|
|
2: ldmia sp!, {r4, pc}^
|
| 389 |
|
|
|
| 390 |
|
|
|
| 391 |
|
|
|
| 392 |
|
|
/* strncpy: String compare function */
|
| 393 |
|
|
@ r0 points to first string
|
| 394 |
|
|
@ r1 points to second string
|
| 395 |
|
|
@ r2 is the number of bytes to compare
|
| 396 |
|
|
@ return the difference if the strings don't match
|
| 397 |
|
|
.globl strncmp
|
| 398 |
|
|
strncmp:
|
| 399 |
|
|
stmdb sp!, {r4, r5, r6, lr}
|
| 400 |
|
|
|
| 401 |
|
|
@ check for 0 length
|
| 402 |
|
|
cmp r2, #0
|
| 403 |
|
|
moveq r0, #1
|
| 404 |
|
|
beq 2f
|
| 405 |
|
|
|
| 406 |
|
|
mov r3, #0
|
| 407 |
|
|
|
| 408 |
|
|
1: add r3, r3, #1
|
| 409 |
|
|
ldrb r4, [r0], #1
|
| 410 |
|
|
ldrb r5, [r1], #1
|
| 411 |
|
|
|
| 412 |
|
|
subs r6, r4, r5
|
| 413 |
|
|
movne r0, r6
|
| 414 |
|
|
bne 2f
|
| 415 |
|
|
|
| 416 |
|
|
cmp r3, r2
|
| 417 |
|
|
moveq r0, #0
|
| 418 |
|
|
beq 2f
|
| 419 |
|
|
|
| 420 |
|
|
b 1b
|
| 421 |
|
|
2: ldmia sp!, {r4, r5, r6, pc}^
|
| 422 |
|
|
|
| 423 |
|
|
|
| 424 |
|
|
|
| 425 |
|
|
.globl init_malloc
|
| 426 |
|
|
init_malloc:
|
| 427 |
|
|
ldr r0, AdrMallocBase
|
| 428 |
|
|
ldr r1, AdrMallocPointer
|
| 429 |
|
|
str r0, [r1]
|
| 430 |
|
|
|
| 431 |
|
|
@ initialize the counter to 0
|
| 432 |
|
|
ldr r1, AdrMallocCount
|
| 433 |
|
|
mov r2, #0
|
| 434 |
|
|
str r2, [r1]
|
| 435 |
|
|
|
| 436 |
|
|
mov pc, lr
|
| 437 |
|
|
|
| 438 |
|
|
|
| 439 |
|
|
/* void *malloc(size_t size); */
|
| 440 |
|
|
.globl malloc
|
| 441 |
|
|
malloc:
|
| 442 |
|
|
/* r0 contains the size of the object in bytes */
|
| 443 |
|
|
ldr r1, AdrMallocPointer
|
| 444 |
|
|
ldr r2, [r1] /* r2 now containts the starting address of the next memory block to use */
|
| 445 |
|
|
add r3, r0, r2 /* r3 contains the address after the end of the new object */
|
| 446 |
|
|
|
| 447 |
|
|
/* Round r3 up to the nearest 0x100 to keep memory aligned */
|
| 448 |
|
|
tst r3, #0xff
|
| 449 |
|
|
beq 1f
|
| 450 |
|
|
bic r3, r3, #0xff
|
| 451 |
|
|
add r3, r3, #0x100
|
| 452 |
|
|
|
| 453 |
|
|
1: str r3, [r1] /* Update the malloc pointer */
|
| 454 |
|
|
mov r0, r2 /* Return the address from before the pointer was updated */
|
| 455 |
|
|
|
| 456 |
|
|
@ Update the block count
|
| 457 |
|
|
ldr r1, AdrMallocCount
|
| 458 |
|
|
ldr r2, [r1]
|
| 459 |
|
|
add r2, r2, #1
|
| 460 |
|
|
str r2, [r1]
|
| 461 |
|
|
|
| 462 |
|
|
mov pc, lr
|
| 463 |
|
|
|
| 464 |
|
|
|
| 465 |
|
|
/* stack at top of ddr3 memory space */
|
| 466 |
|
|
AdrJumpPoint: .word _jump_point
|
| 467 |
|
|
AdrExecBase: .word ADR_EXEC_BASE
|
| 468 |
|
|
AdrStack: .word ADR_STACK
|
| 469 |
|
|
AdrIRQStack: .word ADR_IRQ_STACK
|
| 470 |
|
|
AdrMallocPointer: .word ADR_MALLOC_POINTER
|
| 471 |
|
|
AdrMallocCount: .word ADR_MALLOC_COUNT
|
| 472 |
|
|
AdrMallocBase: .word ADR_MALLOC_BASE
|
| 473 |
|
|
|
| 474 |
|
|
AdrMemCtrl: .word ADR_AMBER_TEST_MEM_CTRL
|
| 475 |
|
|
AdrTestStatus: .word ADR_AMBER_TEST_STATUS
|
| 476 |
|
|
AdrInterruptStatus: .word ADR_AMBER_IC_IRQ0_STATUS
|
| 477 |
|
|
|
| 478 |
|
|
.align 2
|
| 479 |
|
|
AdrATAGBase: .word ATAGBase
|
| 480 |
|
|
AdeEndATAG: .word EndATAG
|
| 481 |
|
|
|
| 482 |
|
|
ATAGBase: .word ATAG_CORE_SIZE
|
| 483 |
|
|
.word ATAG_CORE
|
| 484 |
|
|
.word FLAG_READONLY @ flags
|
| 485 |
|
|
.word 4096 @ page size
|
| 486 |
|
|
.word 0x0 @ rootdev
|
| 487 |
|
|
|
| 488 |
|
|
.word ATAG_MEM_SIZE
|
| 489 |
|
|
.word ATAG_MEM
|
| 490 |
|
|
.word 32*1024*1024 @ size - 32MB
|
| 491 |
|
|
.word 0x0 @ start
|
| 492 |
|
|
|
| 493 |
|
|
.word ATAG_RAMDISK_SIZE
|
| 494 |
|
|
.word ATAG_RAMDISK
|
| 495 |
|
|
.word 1 @ flags: bit 0 = load, bit 1 = prompt
|
| 496 |
|
|
.word 0x000000d0 @ size in 1k blocks
|
| 497 |
|
|
.word 0x00800000 @ physical address of start of ramdisk
|
| 498 |
|
|
|
| 499 |
|
|
.word ATAG_INITRD_SIZE
|
| 500 |
|
|
.word ATAG_INITRD
|
| 501 |
|
|
.word 0x02800000 @ virtual address of start of initrd image
|
| 502 |
|
|
.word 0x00032000 @ size = 200k
|
| 503 |
|
|
|
| 504 |
|
|
.word ATAG_NONE
|
| 505 |
|
|
.word 0x0
|
| 506 |
|
|
EndATAG: .word 0x0
|
| 507 |
|
|
|
| 508 |
|
|
AdrBootParams: .word 0x7c000
|
| 509 |
|
|
AdrPageTabes: .word 0x3f01000
|