1*4d93617dSAlexey Brodkin/* 2*4d93617dSAlexey Brodkin * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved. 3*4d93617dSAlexey Brodkin * 4*4d93617dSAlexey Brodkin * SPDX-License-Identifier: GPL-2.0+ 5*4d93617dSAlexey Brodkin */ 6*4d93617dSAlexey Brodkin 7*4d93617dSAlexey Brodkin#include <asm-offsets.h> 8*4d93617dSAlexey Brodkin#include <config.h> 9*4d93617dSAlexey Brodkin#include <linux/linkage.h> 10*4d93617dSAlexey Brodkin#include <asm/arcregs.h> 11*4d93617dSAlexey Brodkin 12*4d93617dSAlexey Brodkin/* 13*4d93617dSAlexey Brodkin * Note on the LD/ST addressing modes with address register write-back 14*4d93617dSAlexey Brodkin * 15*4d93617dSAlexey Brodkin * LD.a same as LD.aw 16*4d93617dSAlexey Brodkin * 17*4d93617dSAlexey Brodkin * LD.a reg1, [reg2, x] => Pre Incr 18*4d93617dSAlexey Brodkin * Eff Addr for load = [reg2 + x] 19*4d93617dSAlexey Brodkin * 20*4d93617dSAlexey Brodkin * LD.ab reg1, [reg2, x] => Post Incr 21*4d93617dSAlexey Brodkin * Eff Addr for load = [reg2] 22*4d93617dSAlexey Brodkin */ 23*4d93617dSAlexey Brodkin 24*4d93617dSAlexey Brodkin.macro PUSH reg 25*4d93617dSAlexey Brodkin st.a \reg, [%sp, -4] 26*4d93617dSAlexey Brodkin.endm 27*4d93617dSAlexey Brodkin 28*4d93617dSAlexey Brodkin.macro PUSHAX aux 29*4d93617dSAlexey Brodkin lr %r9, [\aux] 30*4d93617dSAlexey Brodkin PUSH %r9 31*4d93617dSAlexey Brodkin.endm 32*4d93617dSAlexey Brodkin 33*4d93617dSAlexey Brodkin.macro SAVE_R1_TO_R24 34*4d93617dSAlexey Brodkin PUSH %r1 35*4d93617dSAlexey Brodkin PUSH %r2 36*4d93617dSAlexey Brodkin PUSH %r3 37*4d93617dSAlexey Brodkin PUSH %r4 38*4d93617dSAlexey Brodkin PUSH %r5 39*4d93617dSAlexey Brodkin PUSH %r6 40*4d93617dSAlexey Brodkin PUSH %r7 41*4d93617dSAlexey Brodkin PUSH %r8 42*4d93617dSAlexey Brodkin PUSH %r9 43*4d93617dSAlexey Brodkin PUSH %r10 44*4d93617dSAlexey Brodkin PUSH %r11 45*4d93617dSAlexey Brodkin PUSH %r12 46*4d93617dSAlexey Brodkin PUSH %r13 47*4d93617dSAlexey Brodkin PUSH %r14 48*4d93617dSAlexey Brodkin PUSH %r15 49*4d93617dSAlexey Brodkin PUSH %r16 50*4d93617dSAlexey Brodkin PUSH %r17 51*4d93617dSAlexey Brodkin PUSH %r18 52*4d93617dSAlexey Brodkin PUSH %r19 53*4d93617dSAlexey Brodkin PUSH %r20 54*4d93617dSAlexey Brodkin PUSH %r21 55*4d93617dSAlexey Brodkin PUSH %r22 56*4d93617dSAlexey Brodkin PUSH %r23 57*4d93617dSAlexey Brodkin PUSH %r24 58*4d93617dSAlexey Brodkin.endm 59*4d93617dSAlexey Brodkin 60*4d93617dSAlexey Brodkin.macro SAVE_ALL_SYS 61*4d93617dSAlexey Brodkin /* saving %r0 to reg->r0 in advance since we read %ecr into it */ 62*4d93617dSAlexey Brodkin st %r0, [%sp, -8] 63*4d93617dSAlexey Brodkin lr %r0, [%ecr] /* all stack addressing is manual so far */ 64*4d93617dSAlexey Brodkin st %r0, [%sp] 65*4d93617dSAlexey Brodkin st %sp, [%sp, -4] 66*4d93617dSAlexey Brodkin /* now move %sp to reg->r0 position so we can do "push" automatically */ 67*4d93617dSAlexey Brodkin sub %sp, %sp, 8 68*4d93617dSAlexey Brodkin 69*4d93617dSAlexey Brodkin SAVE_R1_TO_R24 70*4d93617dSAlexey Brodkin PUSH %r25 71*4d93617dSAlexey Brodkin PUSH %gp 72*4d93617dSAlexey Brodkin PUSH %fp 73*4d93617dSAlexey Brodkin PUSH %blink 74*4d93617dSAlexey Brodkin PUSHAX %eret 75*4d93617dSAlexey Brodkin PUSHAX %erstatus 76*4d93617dSAlexey Brodkin PUSH %lp_count 77*4d93617dSAlexey Brodkin PUSHAX %lp_end 78*4d93617dSAlexey Brodkin PUSHAX %lp_start 79*4d93617dSAlexey Brodkin PUSHAX %erbta 80*4d93617dSAlexey Brodkin.endm 81*4d93617dSAlexey Brodkin 82*4d93617dSAlexey Brodkin.macro SAVE_EXCEPTION_SOURCE 83*4d93617dSAlexey Brodkin#ifdef CONFIG_MMU 84*4d93617dSAlexey Brodkin /* If MMU exists exception faulting address is loaded in EFA reg */ 85*4d93617dSAlexey Brodkin lr %r0, [%efa] 86*4d93617dSAlexey Brodkin#else 87*4d93617dSAlexey Brodkin /* Otherwise in ERET (exception return) reg */ 88*4d93617dSAlexey Brodkin lr %r0, [%eret] 89*4d93617dSAlexey Brodkin#endif 90*4d93617dSAlexey Brodkin.endm 91*4d93617dSAlexey Brodkin 92*4d93617dSAlexey BrodkinENTRY(_start) 93*4d93617dSAlexey Brodkin /* Setup interrupt vector base that matches "__text_start" */ 94*4d93617dSAlexey Brodkin sr __ivt_start, [ARC_AUX_INTR_VEC_BASE] 95*4d93617dSAlexey Brodkin 96*4d93617dSAlexey Brodkin /* Setup stack pointer */ 97*4d93617dSAlexey Brodkin mov %sp, CONFIG_SYS_INIT_SP_ADDR 98*4d93617dSAlexey Brodkin mov %fp, %sp 99*4d93617dSAlexey Brodkin 100*4d93617dSAlexey Brodkin /* Clear bss */ 101*4d93617dSAlexey Brodkin mov %r0, __bss_start 102*4d93617dSAlexey Brodkin mov %r1, __bss_end 103*4d93617dSAlexey Brodkin 104*4d93617dSAlexey Brodkinclear_bss: 105*4d93617dSAlexey Brodkin st.ab 0, [%r0, 4] 106*4d93617dSAlexey Brodkin brlt %r0, %r1, clear_bss 107*4d93617dSAlexey Brodkin 108*4d93617dSAlexey Brodkin /* Zero the one and only argument of "board_init_f" */ 109*4d93617dSAlexey Brodkin mov_s %r0, 0 110*4d93617dSAlexey Brodkin j board_init_f 111*4d93617dSAlexey BrodkinENDPROC(_start) 112*4d93617dSAlexey Brodkin 113*4d93617dSAlexey BrodkinENTRY(memory_error) 114*4d93617dSAlexey Brodkin SAVE_ALL_SYS 115*4d93617dSAlexey Brodkin SAVE_EXCEPTION_SOURCE 116*4d93617dSAlexey Brodkin mov %r1, %sp 117*4d93617dSAlexey Brodkin j do_memory_error 118*4d93617dSAlexey BrodkinENDPROC(memory_error) 119*4d93617dSAlexey Brodkin 120*4d93617dSAlexey BrodkinENTRY(instruction_error) 121*4d93617dSAlexey Brodkin SAVE_ALL_SYS 122*4d93617dSAlexey Brodkin SAVE_EXCEPTION_SOURCE 123*4d93617dSAlexey Brodkin mov %r1, %sp 124*4d93617dSAlexey Brodkin j do_instruction_error 125*4d93617dSAlexey BrodkinENDPROC(instruction_error) 126*4d93617dSAlexey Brodkin 127*4d93617dSAlexey BrodkinENTRY(interrupt_handler) 128*4d93617dSAlexey Brodkin /* Todo - save and restore CPU context when interrupts will be in use */ 129*4d93617dSAlexey Brodkin bl do_interrupt_handler 130*4d93617dSAlexey Brodkin rtie 131*4d93617dSAlexey BrodkinENDPROC(interrupt_handler) 132*4d93617dSAlexey Brodkin 133*4d93617dSAlexey BrodkinENTRY(EV_MachineCheck) 134*4d93617dSAlexey Brodkin SAVE_ALL_SYS 135*4d93617dSAlexey Brodkin SAVE_EXCEPTION_SOURCE 136*4d93617dSAlexey Brodkin mov %r1, %sp 137*4d93617dSAlexey Brodkin j do_machine_check_fault 138*4d93617dSAlexey BrodkinENDPROC(EV_MachineCheck) 139*4d93617dSAlexey Brodkin 140*4d93617dSAlexey BrodkinENTRY(EV_TLBMissI) 141*4d93617dSAlexey Brodkin SAVE_ALL_SYS 142*4d93617dSAlexey Brodkin mov %r0, %sp 143*4d93617dSAlexey Brodkin j do_itlb_miss 144*4d93617dSAlexey BrodkinENDPROC(EV_TLBMissI) 145*4d93617dSAlexey Brodkin 146*4d93617dSAlexey BrodkinENTRY(EV_TLBMissD) 147*4d93617dSAlexey Brodkin SAVE_ALL_SYS 148*4d93617dSAlexey Brodkin mov %r0, %sp 149*4d93617dSAlexey Brodkin j do_dtlb_miss 150*4d93617dSAlexey BrodkinENDPROC(EV_TLBMissD) 151*4d93617dSAlexey Brodkin 152*4d93617dSAlexey BrodkinENTRY(EV_TLBProtV) 153*4d93617dSAlexey Brodkin SAVE_ALL_SYS 154*4d93617dSAlexey Brodkin SAVE_EXCEPTION_SOURCE 155*4d93617dSAlexey Brodkin mov %r1, %sp 156*4d93617dSAlexey Brodkin j do_tlb_prot_violation 157*4d93617dSAlexey BrodkinENDPROC(EV_TLBProtV) 158*4d93617dSAlexey Brodkin 159*4d93617dSAlexey BrodkinENTRY(EV_PrivilegeV) 160*4d93617dSAlexey Brodkin SAVE_ALL_SYS 161*4d93617dSAlexey Brodkin mov %r0, %sp 162*4d93617dSAlexey Brodkin j do_privilege_violation 163*4d93617dSAlexey BrodkinENDPROC(EV_PrivilegeV) 164*4d93617dSAlexey Brodkin 165*4d93617dSAlexey BrodkinENTRY(EV_Trap) 166*4d93617dSAlexey Brodkin SAVE_ALL_SYS 167*4d93617dSAlexey Brodkin mov %r0, %sp 168*4d93617dSAlexey Brodkin j do_trap 169*4d93617dSAlexey BrodkinENDPROC(EV_Trap) 170*4d93617dSAlexey Brodkin 171*4d93617dSAlexey BrodkinENTRY(EV_Extension) 172*4d93617dSAlexey Brodkin SAVE_ALL_SYS 173*4d93617dSAlexey Brodkin mov %r0, %sp 174*4d93617dSAlexey Brodkin j do_extension 175*4d93617dSAlexey BrodkinENDPROC(EV_Extension) 176*4d93617dSAlexey Brodkin 177*4d93617dSAlexey Brodkin/* 178*4d93617dSAlexey Brodkin * void relocate_code (addr_sp, gd, addr_moni) 179*4d93617dSAlexey Brodkin * 180*4d93617dSAlexey Brodkin * This "function" does not return, instead it continues in RAM 181*4d93617dSAlexey Brodkin * after relocating the monitor code. 182*4d93617dSAlexey Brodkin * 183*4d93617dSAlexey Brodkin * r0 = start_addr_sp 184*4d93617dSAlexey Brodkin * r1 = new__gd 185*4d93617dSAlexey Brodkin * r2 = relocaddr 186*4d93617dSAlexey Brodkin */ 187*4d93617dSAlexey BrodkinENTRY(relocate_code) 188*4d93617dSAlexey Brodkin /* 189*4d93617dSAlexey Brodkin * r0-r12 might be clobbered by C functions 190*4d93617dSAlexey Brodkin * so we use r13-r16 for storage here 191*4d93617dSAlexey Brodkin */ 192*4d93617dSAlexey Brodkin mov %r13, %r0 /* save addr_sp */ 193*4d93617dSAlexey Brodkin mov %r14, %r1 /* save addr of gd */ 194*4d93617dSAlexey Brodkin mov %r15, %r2 /* save addr of destination */ 195*4d93617dSAlexey Brodkin 196*4d93617dSAlexey Brodkin mov %r16, %r2 /* %r9 - relocation offset */ 197*4d93617dSAlexey Brodkin sub %r16, %r16, __image_copy_start 198*4d93617dSAlexey Brodkin 199*4d93617dSAlexey Brodkin/* Set up the stack */ 200*4d93617dSAlexey Brodkinstack_setup: 201*4d93617dSAlexey Brodkin mov %sp, %r13 202*4d93617dSAlexey Brodkin mov %fp, %sp 203*4d93617dSAlexey Brodkin 204*4d93617dSAlexey Brodkin/* Check if monitor is loaded right in place for relocation */ 205*4d93617dSAlexey Brodkin mov %r0, __image_copy_start 206*4d93617dSAlexey Brodkin cmp %r0, %r15 /* skip relocation if code loaded */ 207*4d93617dSAlexey Brodkin bz do_board_init_r /* in target location already */ 208*4d93617dSAlexey Brodkin 209*4d93617dSAlexey Brodkin/* Copy data (__image_copy_start - __image_copy_end) to new location */ 210*4d93617dSAlexey Brodkin mov %r1, %r15 211*4d93617dSAlexey Brodkin mov %r2, __image_copy_end 212*4d93617dSAlexey Brodkin sub %r2, %r2, %r0 /* r3 <- amount of bytes to copy */ 213*4d93617dSAlexey Brodkin asr %r2, %r2, 2 /* r3 <- amount of words to copy */ 214*4d93617dSAlexey Brodkin mov %lp_count, %r2 215*4d93617dSAlexey Brodkin lp copy_end 216*4d93617dSAlexey Brodkin ld.ab %r2,[%r0,4] 217*4d93617dSAlexey Brodkin st.ab %r2,[%r1,4] 218*4d93617dSAlexey Brodkincopy_end: 219*4d93617dSAlexey Brodkin 220*4d93617dSAlexey Brodkin/* Fix relocations related issues */ 221*4d93617dSAlexey Brodkin bl do_elf_reloc_fixups 222*4d93617dSAlexey Brodkin#ifndef CONFIG_SYS_ICACHE_OFF 223*4d93617dSAlexey Brodkin bl invalidate_icache_all 224*4d93617dSAlexey Brodkin#endif 225*4d93617dSAlexey Brodkin#ifndef CONFIG_SYS_DCACHE_OFF 226*4d93617dSAlexey Brodkin bl flush_dcache_all 227*4d93617dSAlexey Brodkin#endif 228*4d93617dSAlexey Brodkin 229*4d93617dSAlexey Brodkin/* Update position of intterupt vector table */ 230*4d93617dSAlexey Brodkin lr %r0, [ARC_AUX_INTR_VEC_BASE] /* Read current position */ 231*4d93617dSAlexey Brodkin add %r0, %r0, %r16 /* Update address */ 232*4d93617dSAlexey Brodkin sr %r0, [ARC_AUX_INTR_VEC_BASE] /* Write new position */ 233*4d93617dSAlexey Brodkin 234*4d93617dSAlexey Brodkindo_board_init_r: 235*4d93617dSAlexey Brodkin/* Prepare for exection of "board_init_r" in relocated monitor */ 236*4d93617dSAlexey Brodkin mov %r2, board_init_r /* old address of "board_init_r()" */ 237*4d93617dSAlexey Brodkin add %r2, %r2, %r16 /* new address of "board_init_r()" */ 238*4d93617dSAlexey Brodkin mov %r0, %r14 /* 1-st parameter: gd_t */ 239*4d93617dSAlexey Brodkin mov %r1, %r15 /* 2-nd parameter: dest_addr */ 240*4d93617dSAlexey Brodkin j [%r2] 241*4d93617dSAlexey BrodkinENDPROC(relocate_code) 242