aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/Makefile2
-rw-r--r--arch/powerpc/kernel/asm-offsets.c6
-rw-r--r--arch/powerpc/kernel/head_fsl_booke.S2
-rw-r--r--arch/powerpc/kernel/rtas-rtc.c105
-rw-r--r--arch/powerpc/kernel/setup_64.c5
-rw-r--r--arch/powerpc/kernel/vdso32/datapage.S3
-rw-r--r--arch/powerpc/kernel/vdso32/gettimeofday.S12
-rw-r--r--arch/powerpc/kernel/vdso64/datapage.S1
-rw-r--r--arch/powerpc/kernel/vdso64/gettimeofday.S31
9 files changed, 146 insertions, 21 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 9a74b7ab03a4..046b4bf1f21e 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_PPC_OF) += of_device.o
25procfs-$(CONFIG_PPC64) := proc_ppc64.o 25procfs-$(CONFIG_PPC64) := proc_ppc64.o
26obj-$(CONFIG_PROC_FS) += $(procfs-y) 26obj-$(CONFIG_PROC_FS) += $(procfs-y)
27rtaspci-$(CONFIG_PPC64) := rtas_pci.o 27rtaspci-$(CONFIG_PPC64) := rtas_pci.o
28obj-$(CONFIG_PPC_RTAS) += rtas.o $(rtaspci-y) 28obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y)
29obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o 29obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
30obj-$(CONFIG_RTAS_PROC) += rtas-proc.o 30obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
31obj-$(CONFIG_LPARCFG) += lparcfg.o 31obj-$(CONFIG_LPARCFG) += lparcfg.o
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 4550eb4f4fbd..91538d2445bf 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -270,13 +270,15 @@ int main(void)
270 DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); 270 DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec));
271 DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); 271 DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec));
272 DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); 272 DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec));
273 DEFINE(TSPC64_TV_SEC, offsetof(struct timespec, tv_sec));
274 DEFINE(TSPC64_TV_NSEC, offsetof(struct timespec, tv_nsec));
273 DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec)); 275 DEFINE(TSPC32_TV_SEC, offsetof(struct compat_timespec, tv_sec));
274 DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec)); 276 DEFINE(TSPC32_TV_NSEC, offsetof(struct compat_timespec, tv_nsec));
275#else 277#else
276 DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec)); 278 DEFINE(TVAL32_TV_SEC, offsetof(struct timeval, tv_sec));
277 DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec)); 279 DEFINE(TVAL32_TV_USEC, offsetof(struct timeval, tv_usec));
278 DEFINE(TSPEC32_TV_SEC, offsetof(struct timespec, tv_sec)); 280 DEFINE(TSPC32_TV_SEC, offsetof(struct timespec, tv_sec));
279 DEFINE(TSPEC32_TV_NSEC, offsetof(struct timespec, tv_nsec)); 281 DEFINE(TSPC32_TV_NSEC, offsetof(struct timespec, tv_nsec));
280#endif 282#endif
281 /* timeval/timezone offsets for use by vdso */ 283 /* timeval/timezone offsets for use by vdso */
282 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); 284 DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 5063c603fad4..8d60fa99fc4b 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -24,7 +24,7 @@
24 * Copyright 2002-2004 MontaVista Software, Inc. 24 * Copyright 2002-2004 MontaVista Software, Inc.
25 * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org> 25 * PowerPC 44x support, Matt Porter <mporter@kernel.crashing.org>
26 * Copyright 2004 Freescale Semiconductor, Inc 26 * Copyright 2004 Freescale Semiconductor, Inc
27 * PowerPC e500 modifications, Kumar Gala <kumar.gala@freescale.com> 27 * PowerPC e500 modifications, Kumar Gala <galak@kernel.crashing.org>
28 * 28 *
29 * This program is free software; you can redistribute it and/or modify it 29 * This program is free software; you can redistribute it and/or modify it
30 * under the terms of the GNU General Public License as published by the 30 * under the terms of the GNU General Public License as published by the
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c
new file mode 100644
index 000000000000..7b948662704c
--- /dev/null
+++ b/arch/powerpc/kernel/rtas-rtc.c
@@ -0,0 +1,105 @@
1#include <linux/kernel.h>
2#include <linux/time.h>
3#include <linux/timer.h>
4#include <linux/init.h>
5#include <linux/rtc.h>
6#include <linux/delay.h>
7#include <asm/prom.h>
8#include <asm/rtas.h>
9#include <asm/time.h>
10
11
12#define MAX_RTC_WAIT 5000 /* 5 sec */
13#define RTAS_CLOCK_BUSY (-2)
14unsigned long __init rtas_get_boot_time(void)
15{
16 int ret[8];
17 int error, wait_time;
18 unsigned long max_wait_tb;
19
20 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
21 do {
22 error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
23 if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
24 wait_time = rtas_extended_busy_delay_time(error);
25 /* This is boot time so we spin. */
26 udelay(wait_time*1000);
27 error = RTAS_CLOCK_BUSY;
28 }
29 } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
30
31 if (error != 0 && printk_ratelimit()) {
32 printk(KERN_WARNING "error: reading the clock failed (%d)\n",
33 error);
34 return 0;
35 }
36
37 return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]);
38}
39
40/* NOTE: get_rtc_time will get an error if executed in interrupt context
41 * and if a delay is needed to read the clock. In this case we just
42 * silently return without updating rtc_tm.
43 */
44void rtas_get_rtc_time(struct rtc_time *rtc_tm)
45{
46 int ret[8];
47 int error, wait_time;
48 unsigned long max_wait_tb;
49
50 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
51 do {
52 error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
53 if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
54 if (in_interrupt() && printk_ratelimit()) {
55 memset(&rtc_tm, 0, sizeof(struct rtc_time));
56 printk(KERN_WARNING "error: reading clock"
57 " would delay interrupt\n");
58 return; /* delay not allowed */
59 }
60 wait_time = rtas_extended_busy_delay_time(error);
61 msleep(wait_time);
62 error = RTAS_CLOCK_BUSY;
63 }
64 } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
65
66 if (error != 0 && printk_ratelimit()) {
67 printk(KERN_WARNING "error: reading the clock failed (%d)\n",
68 error);
69 return;
70 }
71
72 rtc_tm->tm_sec = ret[5];
73 rtc_tm->tm_min = ret[4];
74 rtc_tm->tm_hour = ret[3];
75 rtc_tm->tm_mday = ret[2];
76 rtc_tm->tm_mon = ret[1] - 1;
77 rtc_tm->tm_year = ret[0] - 1900;
78}
79
80int rtas_set_rtc_time(struct rtc_time *tm)
81{
82 int error, wait_time;
83 unsigned long max_wait_tb;
84
85 max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
86 do {
87 error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
88 tm->tm_year + 1900, tm->tm_mon + 1,
89 tm->tm_mday, tm->tm_hour, tm->tm_min,
90 tm->tm_sec, 0);
91 if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
92 if (in_interrupt())
93 return 1; /* probably decrementer */
94 wait_time = rtas_extended_busy_delay_time(error);
95 msleep(wait_time);
96 error = RTAS_CLOCK_BUSY;
97 }
98 } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
99
100 if (error != 0 && printk_ratelimit())
101 printk(KERN_WARNING "error: setting the clock failed (%d)\n",
102 error);
103
104 return 0;
105}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index fdbd9f9122f2..608fee7c7e20 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -59,6 +59,7 @@
59#include <asm/firmware.h> 59#include <asm/firmware.h>
60#include <asm/xmon.h> 60#include <asm/xmon.h>
61#include <asm/udbg.h> 61#include <asm/udbg.h>
62#include <asm/kexec.h>
62 63
63#include "setup.h" 64#include "setup.h"
64 65
@@ -415,6 +416,10 @@ void __init setup_system(void)
415 */ 416 */
416 unflatten_device_tree(); 417 unflatten_device_tree();
417 418
419#ifdef CONFIG_KEXEC
420 kexec_setup(); /* requires unflattened device tree. */
421#endif
422
418 /* 423 /*
419 * Fill the ppc64_caches & systemcfg structures with informations 424 * Fill the ppc64_caches & systemcfg structures with informations
420 * retreived from the device-tree. Need to be called before 425 * retreived from the device-tree. Need to be called before
diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S
index a08c26e87835..f6b38472318d 100644
--- a/arch/powerpc/kernel/vdso32/datapage.S
+++ b/arch/powerpc/kernel/vdso32/datapage.S
@@ -77,8 +77,9 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
77 mflr r12 77 mflr r12
78 .cfi_register lr,r12 78 .cfi_register lr,r12
79 bl __get_datapage@local 79 bl __get_datapage@local
80 lwz r3,CFG_TB_TICKS_PER_SEC(r3)
81 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) 80 lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3)
81 lwz r3,CFG_TB_TICKS_PER_SEC(r3)
82 mtlr r12 82 mtlr r12
83 blr
83 .cfi_endproc 84 .cfi_endproc
84V_FUNCTION_END(__kernel_get_tbfreq) 85V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
index aeb5fc9b87b3..0a32a41d50b0 100644
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -83,7 +83,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
83 /* Check for supported clock IDs */ 83 /* Check for supported clock IDs */
84 cmpli cr0,r3,CLOCK_REALTIME 84 cmpli cr0,r3,CLOCK_REALTIME
85 cmpli cr1,r3,CLOCK_MONOTONIC 85 cmpli cr1,r3,CLOCK_MONOTONIC
86 cror cr0,cr0,cr1 86 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
87 bne cr0,99f 87 bne cr0,99f
88 88
89 mflr r12 /* r12 saves lr */ 89 mflr r12 /* r12 saves lr */
@@ -91,7 +91,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
91 mr r10,r3 /* r10 saves id */ 91 mr r10,r3 /* r10 saves id */
92 mr r11,r4 /* r11 saves tp */ 92 mr r11,r4 /* r11 saves tp */
93 bl __get_datapage@local /* get data page */ 93 bl __get_datapage@local /* get data page */
94 mr r9, r3 /* datapage ptr in r9 */ 94 mr r9,r3 /* datapage ptr in r9 */
95 beq cr1,50f /* if monotonic -> jump there */ 95 beq cr1,50f /* if monotonic -> jump there */
96 96
97 /* 97 /*
@@ -173,10 +173,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
173 add r4,r4,r7 173 add r4,r4,r7
174 lis r5,NSEC_PER_SEC@h 174 lis r5,NSEC_PER_SEC@h
175 ori r5,r5,NSEC_PER_SEC@l 175 ori r5,r5,NSEC_PER_SEC@l
176 cmpli cr0,r4,r5 176 cmpl cr0,r4,r5
177 cmpli cr1,r4,0
177 blt 1f 178 blt 1f
178 subf r4,r5,r4 179 subf r4,r5,r4
179 addi r3,r3,1 180 addi r3,r3,1
1811: bge cr1,1f
182 addi r3,r3,-1
183 add r4,r4,r5
1801: stw r3,TSPC32_TV_SEC(r11) 1841: stw r3,TSPC32_TV_SEC(r11)
181 stw r4,TSPC32_TV_NSEC(r11) 185 stw r4,TSPC32_TV_NSEC(r11)
182 186
@@ -210,7 +214,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
210 /* Check for supported clock IDs */ 214 /* Check for supported clock IDs */
211 cmpwi cr0,r3,CLOCK_REALTIME 215 cmpwi cr0,r3,CLOCK_REALTIME
212 cmpwi cr1,r3,CLOCK_MONOTONIC 216 cmpwi cr1,r3,CLOCK_MONOTONIC
213 cror cr0,cr0,cr1 217 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
214 bne cr0,99f 218 bne cr0,99f
215 219
216 li r3,0 220 li r3,0
diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S
index e67eda0f8cda..6393e4137bc7 100644
--- a/arch/powerpc/kernel/vdso64/datapage.S
+++ b/arch/powerpc/kernel/vdso64/datapage.S
@@ -80,5 +80,6 @@ V_FUNCTION_BEGIN(__kernel_get_tbfreq)
80 bl V_LOCAL_FUNC(__get_datapage) 80 bl V_LOCAL_FUNC(__get_datapage)
81 ld r3,CFG_TB_TICKS_PER_SEC(r3) 81 ld r3,CFG_TB_TICKS_PER_SEC(r3)
82 mtlr r12 82 mtlr r12
83 blr
83 .cfi_endproc 84 .cfi_endproc
84V_FUNCTION_END(__kernel_get_tbfreq) 85V_FUNCTION_END(__kernel_get_tbfreq)
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S
index d371c02a8c0e..1a89094715cc 100644
--- a/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ b/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -1,4 +1,5 @@
1/* 1
2 /*
2 * Userland implementation of gettimeofday() for 64 bits processes in a 3 * Userland implementation of gettimeofday() for 64 bits processes in a
3 * ppc64 kernel for use in the vDSO 4 * ppc64 kernel for use in the vDSO
4 * 5 *
@@ -68,7 +69,7 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
68 /* Check for supported clock IDs */ 69 /* Check for supported clock IDs */
69 cmpwi cr0,r3,CLOCK_REALTIME 70 cmpwi cr0,r3,CLOCK_REALTIME
70 cmpwi cr1,r3,CLOCK_MONOTONIC 71 cmpwi cr1,r3,CLOCK_MONOTONIC
71 cror cr0,cr0,cr1 72 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
72 bne cr0,99f 73 bne cr0,99f
73 74
74 mflr r12 /* r12 saves lr */ 75 mflr r12 /* r12 saves lr */
@@ -84,16 +85,17 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
84 85
85 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ 86 bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
86 87
87 lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ 88 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
88 ori r7,r7,0xca00 89 ori r7,r7,16960
89 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ 90 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
90 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ 91 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
91 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */ 92 std r5,TSPC64_TV_SEC(r11) /* store sec in tv */
92 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ 93 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
93 mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / 94 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
94 * XSEC_PER_SEC 95 * XSEC_PER_SEC
95 */ 96 */
96 rldicl r0,r0,44,20 97 rldicl r0,r0,44,20
98 mulli r0,r0,1000 /* nsec = usec * 1000 */
97 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */ 99 std r0,TSPC64_TV_NSEC(r11) /* store nsec in tp */
98 100
99 mtlr r12 101 mtlr r12
@@ -106,15 +108,16 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
106 108
10750: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */ 10950: bl V_LOCAL_FUNC(__do_get_xsec) /* get xsec from tb & kernel */
108 110
109 lis r7,0x3b9a /* r7 = 1000000000 = NSEC_PER_SEC */ 111 lis r7,15 /* r7 = 1000000 = USEC_PER_SEC */
110 ori r7,r7,0xca00 112 ori r7,r7,16960
111 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */ 113 rldicl r5,r4,44,20 /* r5 = sec = xsec / XSEC_PER_SEC */
112 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */ 114 rldicr r6,r5,20,43 /* r6 = sec * XSEC_PER_SEC */
113 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */ 115 subf r0,r6,r4 /* r0 = xsec = (xsec - r6) */
114 mulld r0,r0,r7 /* nsec = (xsec * NSEC_PER_SEC) / 116 mulld r0,r0,r7 /* usec = (xsec * USEC_PER_SEC) /
115 * XSEC_PER_SEC 117 * XSEC_PER_SEC
116 */ 118 */
117 rldicl r6,r0,44,20 119 rldicl r6,r0,44,20
120 mulli r6,r6,1000 /* nsec = usec * 1000 */
118 121
119 /* now we must fixup using wall to monotonic. We need to snapshot 122 /* now we must fixup using wall to monotonic. We need to snapshot
120 * that value and do the counter trick again. Fortunately, we still 123 * that value and do the counter trick again. Fortunately, we still
@@ -123,8 +126,8 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
123 * can be used 126 * can be used
124 */ 127 */
125 128
126 lwz r4,WTOM_CLOCK_SEC(r9) 129 lwa r4,WTOM_CLOCK_SEC(r3)
127 lwz r7,WTOM_CLOCK_NSEC(r9) 130 lwa r7,WTOM_CLOCK_NSEC(r3)
128 131
129 /* We now have our result in r4,r7. We create a fake dependency 132 /* We now have our result in r4,r7. We create a fake dependency
130 * on that result and re-check the counter 133 * on that result and re-check the counter
@@ -144,10 +147,14 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
144 add r7,r7,r6 147 add r7,r7,r6
145 lis r9,NSEC_PER_SEC@h 148 lis r9,NSEC_PER_SEC@h
146 ori r9,r9,NSEC_PER_SEC@l 149 ori r9,r9,NSEC_PER_SEC@l
147 cmpli cr0,r7,r9 150 cmpl cr0,r7,r9
151 cmpli cr1,r7,0
148 blt 1f 152 blt 1f
149 subf r7,r9,r7 153 subf r7,r9,r7
150 addi r4,r4,1 154 addi r4,r4,1
1551: bge cr1,1f
156 addi r4,r4,-1
157 add r7,r7,r9
1511: std r4,TSPC64_TV_SEC(r11) 1581: std r4,TSPC64_TV_SEC(r11)
152 std r7,TSPC64_TV_NSEC(r11) 159 std r7,TSPC64_TV_NSEC(r11)
153 160
@@ -181,7 +188,7 @@ V_FUNCTION_BEGIN(__kernel_clock_getres)
181 /* Check for supported clock IDs */ 188 /* Check for supported clock IDs */
182 cmpwi cr0,r3,CLOCK_REALTIME 189 cmpwi cr0,r3,CLOCK_REALTIME
183 cmpwi cr1,r3,CLOCK_MONOTONIC 190 cmpwi cr1,r3,CLOCK_MONOTONIC
184 cror cr0,cr0,cr1 191 cror cr0*4+eq,cr0*4+eq,cr1*4+eq
185 bne cr0,99f 192 bne cr0,99f
186 193
187 li r3,0 194 li r3,0