summaryrefslogtreecommitdiffstats
path: root/arch/m32r/boot/compressed/head.S
blob: 07cfd6ad1ae460472cd0d5f11cbbeebc62f85b37 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 *  linux/arch/m32r/boot/compressed/head.S
 *
 *  Copyright (c) 2001-2003	Hiroyuki Kondo, Hirokazu Takata,
 *				Hitoshi Yamamoto, Takeo Takahashi
 *  Copyright (c) 2004		Hirokazu Takata
 */

	.text
#include <linux/config.h>
#include <linux/linkage.h>
#include <asm/addrspace.h>
#include <asm/page.h>
#include <asm/assembler.h>

	/*
	 * This code can be loaded anywhere, as long as output will not
	 * overlap it.
	 *
	 * NOTE: This head.S should *NOT* be compiled with -fpic.
	 *
	 */

	.global	startup
	.global __bss_start, _ebss, end, zimage_data, zimage_len
	__ALIGN
startup:
	ldi	r0, #0x0000			/* SPI, disable EI */
	mvtc	r0, psw

	ldi	r12, #-8
	bl	1f
	.fillinsn
1:
	seth	r1, #high(CONFIG_MEMORY_START + 0x00400000) /* Start address */
	add	r12, r14				/* Real address */
	sub	r12, r1					/* difference */

	.global got_len
	seth	r3, #high(_GLOBAL_OFFSET_TABLE_+8)
	or3	r3, r3, #low(_GLOBAL_OFFSET_TABLE_+12)
	add	r3, r14

	/* Update the contents of global offset table */
	ldi	r1, #low(got_len)
	srli	r1, #2
	beqz	r1, 2f
	.fillinsn
1:
	ld	r2, @r3
	add	r2, r12
	st	r2, @r3
	addi	r3, #4
	addi	r1, #-1
	bnez	r1, 1b
	.fillinsn
2:
	/* XXX: resolve plt */

/*
 * Clear BSS first so that there are no surprises...
 */
#ifdef CONFIG_ISA_DUAL_ISSUE
	seth	r2, #high(__bss_start)
	or3	r2, r2, #low(__bss_start)
	add	r2, r12
	seth	r3, #high(_ebss)
	or3	r3, r3, #low(_ebss)
	add	r3, r12
	sub	r3, r2

	; R4 = BSS size in longwords (rounded down)
	mv	r4, r3		    ||	ldi	r1, #0
	srli	r4, #4		    ||	addi	r2, #-4
	beqz	r4, .Lendloop1
.Lloop1:
#ifndef CONFIG_CHIP_M32310
	; Touch memory for the no-write-allocating cache.
	ld	r0, @(4,r2)
#endif
	st	r1, @+r2	    ||	addi	r4, #-1
	st	r1, @+r2
	st	r1, @+r2
	st	r1, @+r2	    ||	cmpeq	r1, r4	; R4 = 0?
	bnc	.Lloop1
.Lendloop1:
	and3	r4, r3, #15
	addi	r2, #4
	beqz	r4, .Lendloop2
.Lloop2:
	stb	r1, @r2		    ||	addi	r4, #-1
	addi	r2, #1
	bnez	r4, .Lloop2
.Lendloop2:

#else /* not CONFIG_ISA_DUAL_ISSUE */
	seth	r2, #high(__bss_start)
	or3	r2, r2, #low(__bss_start)
	add	r2, r12
	seth	r3, #high(_ebss)
	or3	r3, r3, #low(_ebss)
	add	r3, r12
	sub	r3, r2
	mv	r4, r3
	srli	r4, #2		; R4 = BSS size in longwords (rounded down)
	ldi	r1, #0		; clear R1 for longwords store
	addi	r2, #-4		; account for pre-inc store
	beqz	r4, .Lendloop1	; any more to go?
.Lloop1:
	st	r1, @+r2	; yep, zero out another longword
	addi	r4, #-1		; decrement count
	bnez	r4, .Lloop1	; go do some more
.Lendloop1:

#endif /* not CONFIG_ISA_DUAL_ISSUE */

	seth	r1, #high(end)
	or3	r1, r1, #low(end)
	add	r1, r12
	mv	sp, r1

/*
 * decompress the kernel
 */
	mv	r0, sp
	srli	r0, 31				/* MMU is ON or OFF */
        seth	r1, #high(zimage_data)
        or3	r1, r1, #low(zimage_data)
	add	r1, r12
        seth	r2, #high(zimage_len)
        or3	r2, r2, #low(zimage_len)
	mv	r3, sp

	bl	decompress_kernel

#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_VDEC2)
	/* Cache flush */
	ldi	r0, -1
	ldi	r1, 0xd0	; invalidate i-cache, copy back d-cache
	stb	r1, @r0
#elif defined(CONFIG_CHIP_M32102)
	/* Cache flush */
	ldi	r0, -2
	ldi	r1, 0x0100	; invalidate
	stb	r1, @r0
#else
#error "put your cache flush function, please"
#endif

	mv	r0, sp
	srli	r0, 31				/* MMU is ON or OFF */
	slli	r0, 31
	or3	r0, r0, #0x2000
	seth	r1, #high(CONFIG_MEMORY_START)
	or	r0, r1
	jmp	r0

	.balign 512
fake_headers_as_bzImage:
	.short	0
	.ascii	"HdrS"
	.short	0x0202
	.short	0
	.short	0
	.byte	0x00, 0x10
	.short	0
	.byte	0
	.byte	1
	.byte	0x00, 0x80
	.long	0
	.long	0