aboutsummaryrefslogtreecommitdiffstats
path: root/arch/h8300/platform/h8300h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/h8300/platform/h8300h
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/h8300/platform/h8300h')
-rw-r--r--arch/h8300/platform/h8300h/Makefile7
-rw-r--r--arch/h8300/platform/h8300h/aki3068net/Makefile6
-rw-r--r--arch/h8300/platform/h8300h/aki3068net/crt0_ram.S111
-rw-r--r--arch/h8300/platform/h8300h/aki3068net/timer.c52
-rw-r--r--arch/h8300/platform/h8300h/entry.S333
-rw-r--r--arch/h8300/platform/h8300h/generic/Makefile6
-rw-r--r--arch/h8300/platform/h8300h/generic/crt0_ram.S108
-rw-r--r--arch/h8300/platform/h8300h/generic/crt0_rom.S123
-rw-r--r--arch/h8300/platform/h8300h/generic/timer.c96
-rw-r--r--arch/h8300/platform/h8300h/h8max/Makefile6
-rw-r--r--arch/h8300/platform/h8300h/h8max/crt0_ram.S111
-rw-r--r--arch/h8300/platform/h8300h/h8max/timer.c53
-rw-r--r--arch/h8300/platform/h8300h/ints_h8300h.c86
-rw-r--r--arch/h8300/platform/h8300h/ptrace_h8300h.c284
14 files changed, 1382 insertions, 0 deletions
diff --git a/arch/h8300/platform/h8300h/Makefile b/arch/h8300/platform/h8300h/Makefile
new file mode 100644
index 000000000000..5d42c772f75a
--- /dev/null
+++ b/arch/h8300/platform/h8300h/Makefile
@@ -0,0 +1,7 @@
1#
2# Makefile for the linux kernel.
3#
4# Reuse any files we can from the H8/300H
5#
6
7obj-y := entry.o ints_h8300h.o ptrace_h8300h.o
diff --git a/arch/h8300/platform/h8300h/aki3068net/Makefile b/arch/h8300/platform/h8300h/aki3068net/Makefile
new file mode 100644
index 000000000000..b03c328f8c70
--- /dev/null
+++ b/arch/h8300/platform/h8300h/aki3068net/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the linux kernel.
3#
4
5extra-y := crt0_ram.o
6obj-y := timer.o
diff --git a/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S b/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
new file mode 100644
index 000000000000..31c3703d8d60
--- /dev/null
+++ b/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
@@ -0,0 +1,111 @@
1/*
2 * linux/arch/h8300/platform/h8300h/aki3068net/crt0_ram.S
3 *
4 * Yoshinori Sato <ysato@users.sourceforge.jp>
5 *
6 * Platform depend startup
7 * Target Archtecture: AE-3068 (aka. aki3068net)
8 * Memory Layout : RAM
9 */
10
11#define ASSEMBLY
12
13#include <linux/config.h>
14#include <asm/linkage.h>
15
16#if !defined(CONFIG_BLKDEV_RESERVE)
17#if defined(CONFIG_GDB_DEBUG)
18#define RAMEND (__ramend - 0xc000)
19#else
20#define RAMEND __ramend
21#endif
22#else
23#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
24#endif
25
26 .global SYMBOL_NAME(_start)
27 .global SYMBOL_NAME(command_line)
28 .global SYMBOL_NAME(_platform_gpio_table)
29 .global SYMBOL_NAME(_target_name)
30
31 .h8300h
32
33 .section .text
34 .file "crt0_ram.S"
35
36 /* CPU Reset entry */
37SYMBOL_NAME_LABEL(_start)
38 mov.l #RAMEND,sp
39 ldc #0x80,ccr
40
41 /* Peripheral Setup */
42
43#if defined(CONFIG_MTD_UCLINUX)
44 /* move romfs image */
45 jsr @__move_romfs
46#endif
47
48 /* .bss clear */
49 mov.l #__sbss,er5
50 mov.l #__ebss,er4
51 sub.l er5,er4
52 shlr er4
53 shlr er4
54 sub.l er0,er0
551:
56 mov.l er0,@er5
57 adds #4,er5
58 dec.l #1,er4
59 bne 1b
60
61 /* copy kernel commandline */
62 mov.l #COMMAND_START,er5
63 mov.l #SYMBOL_NAME(command_line),er6
64 mov.w #512,r4
65 eepmov.w
66
67 /* uClinux kernel start */
68 ldc #0x90,ccr /* running kernel */
69 mov.l #SYMBOL_NAME(init_thread_union),sp
70 add.l #0x2000,sp
71 jsr @_start_kernel
72_exit:
73
74 jmp _exit
75
76 rts
77
78 /* I/O port assign information */
79__platform_gpio_table:
80 mov.l #gpio_table,er0
81 rts
82
83gpio_table:
84 ;; P1DDR
85 .byte 0xff,0xff
86 ;; P2DDR
87 .byte 0xff,0xff
88 ;; P3DDR
89 .byte 0xff,0x00
90 ;; P4DDR
91 .byte 0x00,0x00
92 ;; P5DDR
93 .byte 0x01,0x01
94 ;; P6DDR
95 .byte 0x00,0x00
96 ;; dummy
97 .byte 0x00,0x00
98 ;; P8DDR
99 .byte 0x0c,0x0c
100 ;; P9DDR
101 .byte 0x00,0x00
102 ;; PADDR
103 .byte 0x00,0x00
104 ;; PBDDR
105 .byte 0x30,0x30
106
107__target_name:
108 .asciz "AE-3068"
109
110 .section .bootvec,"ax"
111 jmp @SYMBOL_NAME(_start)
diff --git a/arch/h8300/platform/h8300h/aki3068net/timer.c b/arch/h8300/platform/h8300h/aki3068net/timer.c
new file mode 100644
index 000000000000..086efb1fd283
--- /dev/null
+++ b/arch/h8300/platform/h8300h/aki3068net/timer.c
@@ -0,0 +1,52 @@
1/*
2 * linux/arch/h8300/platform/h8300h/aki3068net/timer.c
3 *
4 * Yoshinori Sato <ysato@users.sourcefoge.jp>
5 *
6 * Platform depend Timer Handler
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/param.h>
15#include <linux/string.h>
16#include <linux/mm.h>
17#include <linux/interrupt.h>
18#include <linux/init.h>
19#include <linux/timex.h>
20
21#include <asm/segment.h>
22#include <asm/io.h>
23#include <asm/irq.h>
24#include <asm/regs306x.h>
25
26#define CMFA 6
27
28#define CMIEA 0x40
29#define CCLR_CMA 0x08
30#define CLK_DIV8192 0x03
31
32#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
33
34void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
35{
36 /* setup 8bit timer ch2 */
37 ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2); /* set interval */
38 ctrl_outb(0x00, _8TCSR2); /* no output */
39 request_irq(40, timer_int, 0, "timer", 0);
40 ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */
41}
42
43void platform_timer_eoi(void)
44{
45 *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
46}
47
48void platform_gettod(int *year, int *mon, int *day, int *hour,
49 int *min, int *sec)
50{
51 *year = *mon = *day = *hour = *min = *sec = 0;
52}
diff --git a/arch/h8300/platform/h8300h/entry.S b/arch/h8300/platform/h8300h/entry.S
new file mode 100644
index 000000000000..2052dbb9483f
--- /dev/null
+++ b/arch/h8300/platform/h8300h/entry.S
@@ -0,0 +1,333 @@
1/* -*- mode: asm -*-
2 *
3 * linux/arch/h8300/platform/h8300h/entry.S
4 *
5 * Yoshinori Sato <ysato@users.sourceforge.jp>
6 * David McCullough <davidm@snapgear.com>
7 *
8 */
9
10/*
11 * entry.S
12 * include exception/interrupt gateway
13 * system call entry
14 */
15
16#include <linux/sys.h>
17#include <linux/config.h>
18#include <asm/unistd.h>
19#include <asm/setup.h>
20#include <asm/segment.h>
21#include <asm/linkage.h>
22#include <asm/asm-offsets.h>
23#include <asm/thread_info.h>
24#include <asm/errno.h>
25
26 .h8300h
27
28/* CPU context save/restore macros. */
29
30 .macro SAVE_ALL
31 mov.l er0,@-sp
32
33 stc ccr,r0l /* check kernel mode */
34 orc #0x10,ccr
35 btst #4,r0l
36 bne 5f
37
38 mov.l sp,@SYMBOL_NAME(sw_usp) /* user mode */
39 mov.l @sp,er0
40 mov.l @SYMBOL_NAME(sw_ksp),sp
41 sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */
42 mov.l er0,@-sp
43 mov.l er1,@-sp
44 mov.l @SYMBOL_NAME(sw_usp),er0
45 mov.l @(8:16,er0),er1 /* copy the RET addr */
46 mov.l er1,@(LRET-LER1:16,sp)
47
48 mov.w e1,r1 /* e1 highbyte = ccr */
49 and #0xef,r1h /* mask mode? flag */
50 sub.w r0,r0
51 mov.b r1h,r0l
52 mov.w r0,@(LCCR-LER1:16,sp) /* copy ccr */
53 mov.l @(LORIG-LER1:16,sp),er0
54 mov.l er0,@(LER0-LER1:16,sp) /* copy ER0 */
55 bra 6f
565:
57 mov.l @sp,er0 /* kernel mode */
58 subs #2,sp /* dummy ccr */
59 mov.l er0,@-sp
60 mov.l er1,@-sp
61 mov.w @(LRET-LER1:16,sp),r1 /* copy old ccr */
62 mov.b r1h,r1l
63 mov.b #0,r1h
64 mov.w r1,@(LCCR-LER1:16,sp) /* set ccr */
656:
66 mov.l er2,@-sp
67 mov.l er3,@-sp
68 mov.l er6,@-sp /* syscall arg #6 */
69 mov.l er5,@-sp /* syscall arg #5 */
70 mov.l er4,@-sp /* syscall arg #4 */
71 .endm
72
73 .macro RESTORE_ALL
74 mov.l @sp+,er4
75 mov.l @sp+,er5
76 mov.l @sp+,er6
77 mov.l @sp+,er3
78 mov.l @sp+,er2
79 mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */
80 btst #4,r0l
81 bne 7f
82
83 orc #0x80,ccr
84 mov.l @SYMBOL_NAME(sw_usp),er0
85 mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */
86 mov.l er1,@er0
87 mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */
88 mov.b r1l,r1h
89 mov.b @(LRET+1-LER1:16,sp),r1l
90 mov.w r1,e1
91 mov.w @(LRET+2-LER1:16,sp),r1
92 mov.l er1,@(8:16,er0)
93
94 mov.l @sp+,er1
95 add.l #(LRET-LER1),sp /* remove LORIG - LRET */
96 mov.l sp,@SYMBOL_NAME(sw_ksp)
97 mov.l er0,sp
98 bra 8f
997:
100 mov.l @sp+,er1
101 adds #4,sp
102 adds #2,sp
1038:
104 mov.l @sp+,er0
105 adds #4,sp /* remove the sw created LVEC */
106 rte
107 .endm
108
109.globl SYMBOL_NAME(system_call)
110.globl SYMBOL_NAME(ret_from_exception)
111.globl SYMBOL_NAME(ret_from_fork)
112.globl SYMBOL_NAME(ret_from_interrupt)
113.globl SYMBOL_NAME(interrupt_redirect_table)
114.globl SYMBOL_NAME(sw_ksp),SYMBOL_NAME(sw_usp)
115.globl SYMBOL_NAME(resume)
116.globl SYMBOL_NAME(interrupt_redirect_table)
117.globl SYMBOL_NAME(interrupt_entry)
118.globl SYMBOL_NAME(system_call)
119.globl SYMBOL_NAME(trace_break)
120
121#if defined(CONFIG_ROMKERNEL)
122INTERRUPTS = 64
123 .section .int_redirect,"ax"
124SYMBOL_NAME_LABEL(interrupt_redirect_table)
125 .rept 7
126 .long 0
127 .endr
128 jsr @SYMBOL_NAME(interrupt_entry) /* NMI */
129 jmp @SYMBOL_NAME(system_call) /* TRAPA #0 (System call) */
130 .long 0
131 .long 0
132 jmp @SYMBOL_NAME(trace_break) /* TRAPA #3 (breakpoint) */
133 .rept INTERRUPTS-12
134 jsr @SYMBOL_NAME(interrupt_entry)
135 .endr
136#endif
137#if defined(CONFIG_RAMKERNEL)
138.globl SYMBOL_NAME(interrupt_redirect_table)
139 .section .bss
140SYMBOL_NAME_LABEL(interrupt_redirect_table)
141 .space 4
142#endif
143
144 .section .text
145 .align 2
146SYMBOL_NAME_LABEL(interrupt_entry)
147 SAVE_ALL
148 mov.w @(LCCR,sp),r0
149 btst #4,r0l
150 bne 1f
151 mov.l @SYMBOL_NAME(sw_usp),er0
152 mov.l @(4:16,er0),er0
153 bra 2f
1541:
155 mov.l @(LVEC,sp),er0
1562:
157#if defined(CONFIG_ROMKERNEL)
158 sub.l #SYMBOL_NAME(interrupt_redirect_table),er0
159#endif
160#if defined(CONFIG_RAMKERNEL)
161 mov.l @SYMBOL_NAME(interrupt_redirect_table),er1
162 sub.l er1,er0
163#endif
164 shlr.l er0
165 shlr.l er0
166 dec.l #1,er0
167 mov.l sp,er1
168 subs #4,er1 /* adjust ret_pc */
169 jsr @SYMBOL_NAME(process_int)
170 mov.l @SYMBOL_NAME(irq_stat)+CPUSTAT_SOFTIRQ_PENDING,er0
171 beq 1f
172 jsr @SYMBOL_NAME(do_softirq)
1731:
174 jmp @SYMBOL_NAME(ret_from_interrupt)
175
176SYMBOL_NAME_LABEL(system_call)
177 subs #4,sp /* dummy LVEC */
178 SAVE_ALL
179 mov.w @(LCCR:16,sp),r1
180 bset #4,r1l
181 ldc r1l,ccr
182 mov.l er0,er4
183 mov.l #-ENOSYS,er0
184 mov.l er0,@(LER0:16,sp)
185
186 /* save top of frame */
187 mov.l sp,er0
188 jsr @SYMBOL_NAME(set_esp0)
189 cmp.l #NR_syscalls,er4
190 bcc SYMBOL_NAME(ret_from_exception):16
191 shll.l er4
192 shll.l er4
193 mov.l #SYMBOL_NAME(sys_call_table),er0
194 add.l er4,er0
195 mov.l @er0,er4
196 beq SYMBOL_NAME(ret_from_exception):16
197 mov.l sp,er2
198 and.w #0xe000,r2
199 mov.b @((TASK_FLAGS+3-(TIF_SYSCALL_TRACE >> 3)):16,er2),r2l
200 btst #(TIF_SYSCALL_TRACE & 7),r2l
201 bne 1f
202 mov.l @(LER1:16,sp),er0
203 mov.l @(LER2:16,sp),er1
204 mov.l @(LER3:16,sp),er2
205 jsr @er4
206 mov.l er0,@(LER0:16,sp) /* save the return value */
207#if defined(CONFIG_SYSCALL_PRINT)
208 jsr @SYMBOL_NAME(syscall_print)
209#endif
210 bra SYMBOL_NAME(ret_from_exception):8
2111:
212 jsr SYMBOL_NAME(syscall_trace)
213 mov.l @(LER1:16,sp),er0
214 mov.l @(LER2:16,sp),er1
215 mov.l @(LER3:16,sp),er2
216 jsr @er4
217 mov.l er0,@(LER0:16,sp) /* save the return value */
218 jsr @SYMBOL_NAME(syscall_trace)
219 bra SYMBOL_NAME(ret_from_exception):8
220
221SYMBOL_NAME_LABEL(ret_from_fork)
222 mov.l er2,er0
223 jsr @SYMBOL_NAME(schedule_tail)
224 bra SYMBOL_NAME(ret_from_exception):8
225
226SYMBOL_NAME_LABEL(reschedule)
227 /* save top of frame */
228 mov.l sp,er0
229 jsr @SYMBOL_NAME(set_esp0)
230 jsr @SYMBOL_NAME(schedule)
231
232SYMBOL_NAME_LABEL(ret_from_exception)
233#if defined(CONFIG_PREEMPT)
234 orc #0x80,ccr
235#endif
236SYMBOL_NAME_LABEL(ret_from_interrupt)
237 mov.b @(LCCR+1:16,sp),r0l
238 btst #4,r0l /* check if returning to kernel */
239 bne done:8 /* if so, skip resched, signals */
240 andc #0x7f,ccr
241 mov.l sp,er4
242 and.w #0xe000,r4
243 mov.l @(TI_FLAGS:16,er4),er1
244 and.l #_TIF_WORK_MASK,er1
245 beq done:8
2461:
247 mov.l @(TI_FLAGS:16,er4),er1
248 btst #TIF_NEED_RESCHED,r1l
249 bne SYMBOL_NAME(reschedule):16
250 mov.l sp,er0
251 subs #4,er0 /* adjust retpc */
252 mov.l er2,er1
253 jsr @SYMBOL_NAME(do_signal)
254#if defined(CONFIG_PREEMPT)
255 bra done:8 /* userspace thoru */
2563:
257 btst #4,r0l
258 beq done:8 /* userspace thoru */
2594:
260 mov.l @(TI_PRE_COUNT:16,er4),er1
261 bne done:8
262 mov.l @(TI_FLAGS:16,er4),er1
263 btst #TIF_NEED_RESCHED,r1l
264 beq done:8
265 mov.b r0l,r0l
266 bpl done:8 /* interrupt off (exception path?) */
267 mov.l #PREEMPT_ACTIVE,er1
268 mov.l er1,@(TI_PRE_COUNT:16,er4)
269 andc #0x7f,ccr
270 jsr @SYMBOL_NAME(schedule)
271 sub.l er1,er1
272 mov.l er1,@(TI_PRE_COUNT:16,er4)
273 orc #0x80,ccr
274 bra 4b:8
275#endif
276done:
277 RESTORE_ALL /* Does RTE */
278
279SYMBOL_NAME_LABEL(resume)
280 /*
281 * Beware - when entering resume, offset of tss is in d1,
282 * prev (the current task) is in a0, next (the new task)
283 * is in a1 and d2.b is non-zero if the mm structure is
284 * shared between the tasks, so don't change these
285 * registers until their contents are no longer needed.
286 */
287
288 /* save sr */
289 sub.w r3,r3
290 stc ccr,r3l
291 mov.w r3,@(THREAD_CCR+2:16,er0)
292
293 /* disable interrupts */
294 orc #0x80,ccr
295 mov.l @SYMBOL_NAME(sw_usp),er3
296 mov.l er3,@(THREAD_USP:16,er0)
297 mov.l sp,@(THREAD_KSP:16,er0)
298
299 /* Skip address space switching if they are the same. */
300 /* FIXME: what did we hack out of here, this does nothing! */
301
302 mov.l @(THREAD_USP:16,er1),er0
303 mov.l er0,@SYMBOL_NAME(sw_usp)
304 mov.l @(THREAD_KSP:16,er1),sp
305
306 /* restore status register */
307 mov.w @(THREAD_CCR+2:16,er1),r3
308
309 ldc r3l,ccr
310 rts
311
312SYMBOL_NAME_LABEL(trace_break)
313 subs #4,sp
314 SAVE_ALL
315 sub.l er1,er1
316 dec.l #1,er1
317 mov.l er1,@(LORIG,sp)
318 mov.l sp,er0
319 jsr @SYMBOL_NAME(set_esp0)
320 mov.l @SYMBOL_NAME(sw_usp),er0
321 mov.l @er0,er1
322 subs #2,er1
323 mov.l er1,@er0
324 and.w #0xff,e1
325 mov.l er1,er0
326 jsr @SYMBOL_NAME(trace_trap)
327 jmp @SYMBOL_NAME(ret_from_exception)
328
329 .section .bss
330SYMBOL_NAME_LABEL(sw_ksp)
331 .space 4
332SYMBOL_NAME_LABEL(sw_usp)
333 .space 4
diff --git a/arch/h8300/platform/h8300h/generic/Makefile b/arch/h8300/platform/h8300h/generic/Makefile
new file mode 100644
index 000000000000..b6ea7688a616
--- /dev/null
+++ b/arch/h8300/platform/h8300h/generic/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the linux kernel.
3#
4
5obj-y := timer.o
6extra-y = crt0_$(MODEL).o
diff --git a/arch/h8300/platform/h8300h/generic/crt0_ram.S b/arch/h8300/platform/h8300h/generic/crt0_ram.S
new file mode 100644
index 000000000000..b735042a7c3f
--- /dev/null
+++ b/arch/h8300/platform/h8300h/generic/crt0_ram.S
@@ -0,0 +1,108 @@
1/*
2 * linux/arch/h8300/platform/h8300h/generic/crt0_ram.S
3 *
4 * Yoshinori Sato <ysato@users.sourceforge.jp>
5 *
6 * Platform depend startup
7 * Target Archtecture: AE-3068 (aka. aki3068net)
8 * Memory Layout : RAM
9 */
10
11#define ASSEMBLY
12
13#include <linux/config.h>
14#include <asm/linkage.h>
15
16#if !defined(CONFIG_BLKDEV_RESERVE)
17#if defined(CONFIG_GDB_DEBUG)
18#define RAMEND (__ramend - 0xc000)
19#else
20#define RAMEND __ramend
21#endif
22#else
23#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
24#endif
25
26 .global SYMBOL_NAME(_start)
27 .global SYMBOL_NAME(command_line)
28 .global SYMBOL_NAME(_platform_gpio_table)
29 .global SYMBOL_NAME(_target_name)
30
31 .h8300h
32
33 .section .text
34 .file "crt0_ram.S"
35
36 /* CPU Reset entry */
37SYMBOL_NAME_LABEL(_start)
38 mov.l #RAMEND,sp
39 ldc #0x80,ccr
40
41 /* Peripheral Setup */
42
43#if defined(CONFIG_BLK_DEV_BLKMEM)
44 /* move romfs image */
45 jsr @__move_romfs
46#endif
47
48 /* .bss clear */
49 mov.l #__sbss,er5
50 mov.l #__ebss,er4
51 sub.l er5,er4
52 shlr er4
53 shlr er4
54 sub.l er0,er0
551:
56 mov.l er0,@er5
57 adds #4,er5
58 dec.l #1,er4
59 bne 1b
60
61 /* copy kernel commandline */
62 mov.l #COMMAND_START,er5
63 mov.l #SYMBOL_NAME(command_line),er6
64 mov.w #512,r4
65 eepmov.w
66
67 /* uClinux kernel start */
68 ldc #0x90,ccr /* running kernel */
69 mov.l #SYMBOL_NAME(init_thread_union),sp
70 add.l #0x2000,sp
71 jsr @_start_kernel
72_exit:
73
74 jmp _exit
75
76 rts
77
78 /* I/O port assign information */
79__platform_gpio_table:
80 mov.l #gpio_table,er0
81 rts
82
83gpio_table:
84 ;; P1DDR
85 .byte 0x00,0x00
86 ;; P2DDR
87 .byte 0x00,0x00
88 ;; P3DDR
89 .byte 0x00,0x00
90 ;; P4DDR
91 .byte 0x00,0x00
92 ;; P5DDR
93 .byte 0x00,0x00
94 ;; P6DDR
95 .byte 0x00,0x00
96 ;; dummy
97 .byte 0x00,0x00
98 ;; P8DDR
99 .byte 0x00,0x00
100 ;; P9DDR
101 .byte 0x00,0x00
102 ;; PADDR
103 .byte 0x00,0x00
104 ;; PBDDR
105 .byte 0x00,0x00
106
107__target_name:
108 .asciz "generic"
diff --git a/arch/h8300/platform/h8300h/generic/crt0_rom.S b/arch/h8300/platform/h8300h/generic/crt0_rom.S
new file mode 100644
index 000000000000..2e32d8179db3
--- /dev/null
+++ b/arch/h8300/platform/h8300h/generic/crt0_rom.S
@@ -0,0 +1,123 @@
1/*
2 * linux/arch/h8300/platform/h8300h/generic/crt0_rom.S
3 *
4 * Yoshinori Sato <ysato@users.sourceforge.jp>
5 *
6 * Platform depend startup
7 * Target Archtecture: generic
8 * Memory Layout : ROM
9 */
10
11#define ASSEMBLY
12
13#include <linux/config.h>
14#include <asm/linkage.h>
15
16 .global SYMBOL_NAME(_start)
17 .global SYMBOL_NAME(_command_line)
18 .global SYMBOL_NAME(_platform_gpio_table)
19 .global SYMBOL_NAME(_target_name)
20
21 .h8300h
22 .section .text
23 .file "crt0_rom.S"
24
25 /* CPU Reset entry */
26SYMBOL_NAME_LABEL(_start)
27 mov.l #__ramend,sp
28 ldc #0x80,ccr
29
30 /* Peripheral Setup */
31
32 /* .bss clear */
33 mov.l #__sbss,er5
34 mov.l #__ebss,er4
35 sub.l er5,er4
36 shlr er4
37 shlr er4
38 sub.l er0,er0
391:
40 mov.l er0,@er5
41 adds #4,er5
42 dec.l #1,er4
43 bne 1b
44
45 /* copy .data */
46#if !defined(CONFIG_H8300H_SIM)
47 /* copy .data */
48 mov.l #__begin_data,er5
49 mov.l #__sdata,er6
50 mov.l #__edata,er4
51 sub.l er6,er4
52 shlr.l er4
53 shlr.l er4
541:
55 mov.l @er5+,er0
56 mov.l er0,@er6
57 adds #4,er6
58 dec.l #1,er4
59 bne 1b
60#endif
61
62 /* copy kernel commandline */
63 mov.l #COMMAND_START,er5
64 mov.l #SYMBOL_NAME(_command_line),er6
65 mov.w #512,r4
66 eepmov.w
67
68 /* linux kernel start */
69 ldc #0x90,ccr /* running kernel */
70 mov.l #SYMBOL_NAME(init_thread_union),sp
71 add.l #0x2000,sp
72 jsr @_start_kernel
73_exit:
74
75 jmp _exit
76
77 rts
78
79 /* I/O port assign information */
80__platform_gpio_table:
81 mov.l #gpio_table,er0
82 rts
83
84gpio_table:
85 ;; P1DDR
86 .byte 0x00,0x00
87 ;; P2DDR
88 .byte 0x00,0x00
89 ;; P3DDR
90 .byte 0x00,0x00
91 ;; P4DDR
92 .byte 0x00,0x00
93 ;; P5DDR
94 .byte 0x00,0x00
95 ;; P6DDR
96 .byte 0x00,0x00
97 ;; dummy
98 .byte 0x00,0x00
99 ;; P8DDR
100 .byte 0x00,0x00
101 ;; P9DDR
102 .byte 0x00,0x00
103 ;; PADDR
104 .byte 0x00,0x00
105 ;; PBDDR
106 .byte 0x00,0x00
107
108 .section .rodata
109__target_name:
110 .asciz "generic"
111
112 .section .bss
113__command_line:
114 .space 512
115
116 /* interrupt vector */
117 .section .vectors,"ax"
118 .long __start
119vector = 1
120 .rept 64-1
121 .long _interrupt_redirect_table+vector*4
122vector = vector + 1
123 .endr
diff --git a/arch/h8300/platform/h8300h/generic/timer.c b/arch/h8300/platform/h8300h/generic/timer.c
new file mode 100644
index 000000000000..6590f89e521a
--- /dev/null
+++ b/arch/h8300/platform/h8300h/generic/timer.c
@@ -0,0 +1,96 @@
1/*
2 * linux/arch/h8300/platform/h8300h/generic/timer.c
3 *
4 * Yoshinori Sato <ysato@users.sourceforge.jp>
5 *
6 * Platform depend Timer Handler
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/param.h>
15#include <linux/string.h>
16#include <linux/mm.h>
17#include <linux/interrupt.h>
18
19#include <asm/segment.h>
20#include <asm/io.h>
21#include <asm/irq.h>
22
23#include <linux/timex.h>
24
25#if defined(CONFIG_H83007) || defined(CONFIG_H83068)
26#include <asm/regs306x.h>
27#define CMFA 6
28
29#define CMIEA 0x40
30#define CCLR_CMA 0x08
31#define CLK_DIV8192 0x03
32
33#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
34
35void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
36{
37 /* setup 8bit timer ch2 */
38 ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2); /* set interval */
39 ctrl_outb(0x00, _8TCSR2); /* no output */
40 request_irq(40, timer_int, 0, "timer", 0);
41 ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */
42}
43
44void platform_timer_eoi(void)
45{
46 *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
47}
48#endif
49
50#if defined(CONFIG_H83002) || defined(CONFIG_H83048)
51/* FIXME! */
52#define TSTR 0x00ffff60
53#define TSNC 0x00ffff61
54#define TMDR 0x00ffff62
55#define TFCR 0x00ffff63
56#define TOER 0x00ffff90
57#define TOCR 0x00ffff91
58/* ITU0 */
59#define TCR 0x00ffff64
60#define TIOR 0x00ffff65
61#define TIER 0x00ffff66
62#define TSR 0x00ffff67
63#define TCNT 0x00ffff68
64#define GRA 0x00ffff6a
65#define GRB 0x00ffff6c
66
67#define CCLR_CMGRA 0x20
68#define CLK_DIV8 0x03
69
70#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8 /* Timer input freq. */
71
72void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
73{
74 *(unsigned short *)GRA= H8300_TIMER_FREQ / HZ; /* set interval */
75 *(unsigned short *)TCNT=0; /* clear counter */
76 ctrl_outb(0x80|CCLR_CMGRA|CLK_DIV8, TCR); /* set ITU0 clock */
77 ctrl_outb(0x88, TIOR); /* no output */
78 request_irq(26, timer_int, 0, "timer", 0);
79 ctrl_outb(0xf9, TIER); /* compare match GRA interrupt */
80 ctrl_outb(ctrl_inb(TSNC) & ~0x01, TSNC); /* ITU0 async */
81 ctrl_outb(ctrl_inb(TMDR) & ~0x01, TMDR); /* ITU0 normal mode */
82 ctrl_outb(ctrl_inb(TSTR) | 0x01, TSTR); /* ITU0 Start */
83 return 0;
84}
85
86void platform_timer_eoi(void)
87{
88 ctrl_outb(ctrl_inb(TSR) & ~0x01,TSR);
89}
90#endif
91
92void platform_gettod(int *year, int *mon, int *day, int *hour,
93 int *min, int *sec)
94{
95 *year = *mon = *day = *hour = *min = *sec = 0;
96}
diff --git a/arch/h8300/platform/h8300h/h8max/Makefile b/arch/h8300/platform/h8300h/h8max/Makefile
new file mode 100644
index 000000000000..b03c328f8c70
--- /dev/null
+++ b/arch/h8300/platform/h8300h/h8max/Makefile
@@ -0,0 +1,6 @@
1#
2# Makefile for the linux kernel.
3#
4
5extra-y := crt0_ram.o
6obj-y := timer.o
diff --git a/arch/h8300/platform/h8300h/h8max/crt0_ram.S b/arch/h8300/platform/h8300h/h8max/crt0_ram.S
new file mode 100644
index 000000000000..a5c5a9156e04
--- /dev/null
+++ b/arch/h8300/platform/h8300h/h8max/crt0_ram.S
@@ -0,0 +1,111 @@
1/*
2 * linux/arch/h8300/platform/h8300h/h8max/crt0_ram.S
3 *
4 * Yoshinori Sato <ysato@users.sourceforge.jp>
5 *
6 * Platform depend startup
7 * Target Archtecture: H8MAX
8 * Memory Layout : RAM
9 */
10
11#define ASSEMBLY
12
13#include <linux/config.h>
14#include <asm/linkage.h>
15
16#if !defined(CONFIG_BLKDEV_RESERVE)
17#if defined(CONFIG_GDB_DEBUG)
18#define RAMEND (__ramend - 0xc000)
19#else
20#define RAMEND __ramend
21#endif
22#else
23#define RAMEND CONFIG_BLKDEV_RESERVE_ADDRESS
24#endif
25
26 .global SYMBOL_NAME(_start)
27 .global SYMBOL_NAME(command_line)
28 .global SYMBOL_NAME(_platform_gpio_table)
29 .global SYMBOL_NAME(_target_name)
30
31 .h8300h
32
33 .section .text
34 .file "crt0_ram.S"
35
36 /* CPU Reset entry */
37SYMBOL_NAME_LABEL(_start)
38 mov.l #RAMEND,sp
39 ldc #0x80,ccr
40
41 /* Peripheral Setup */
42
43#if defined(CONFIG_MTD_UCLINUX)
44 /* move romfs image */
45 jsr @__move_romfs
46#endif
47
48 /* .bss clear */
49 mov.l #__sbss,er5
50 mov.l #__ebss,er4
51 sub.l er5,er4
52 shlr er4
53 shlr er4
54 sub.l er0,er0
551:
56 mov.l er0,@er5
57 adds #4,er5
58 dec.l #1,er4
59 bne 1b
60
61 /* copy kernel commandline */
62 mov.l #COMMAND_START,er5
63 mov.l #SYMBOL_NAME(command_line),er6
64 mov.w #512,r4
65 eepmov.w
66
67 /* uClinux kernel start */
68 ldc #0x90,ccr /* running kernel */
69 mov.l #SYMBOL_NAME(init_thread_union),sp
70 add.l #0x2000,sp
71 jsr @_start_kernel
72_exit:
73
74 jmp _exit
75
76 rts
77
78 /* I/O port assign information */
79__platform_gpio_table:
80 mov.l #gpio_table,er0
81 rts
82
83gpio_table:
84 ;; P1DDR
85 .byte 0xff,0xff
86 ;; P2DDR
87 .byte 0xff,0xff
88 ;; P3DDR
89 .byte 0x00,0x00
90 ;; P4DDR
91 .byte 0x00,0x00
92 ;; P5DDR
93 .byte 0x01,0x01
94 ;; P6DDR
95 .byte 0xf6,0xf6
96 ;; dummy
97 .byte 0x00,0x00
98 ;; P8DDR
99 .byte 0xee,0xee
100 ;; P9DDR
101 .byte 0x00,0x00
102 ;; PADDR
103 .byte 0x00,0x00
104 ;; PBDDR
105 .byte 0x30,0x30
106
107__target_name:
108 .asciz "H8MAX"
109
110 .section .bootvec,"ax"
111 jmp @SYMBOL_NAME(_start)
diff --git a/arch/h8300/platform/h8300h/h8max/timer.c b/arch/h8300/platform/h8300h/h8max/timer.c
new file mode 100644
index 000000000000..9ac9fa6691c0
--- /dev/null
+++ b/arch/h8300/platform/h8300h/h8max/timer.c
@@ -0,0 +1,53 @@
1/*
2 * linux/arch/h8300/platform/h8300h/h8max/timer.c
3 *
4 * Yoshinori Sato <ysato@users.sourcefoge.jp>
5 *
6 * Platform depend Timer Handler
7 *
8 */
9
10#include <linux/config.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/kernel.h>
14#include <linux/param.h>
15#include <linux/string.h>
16#include <linux/mm.h>
17#include <linux/interrupt.h>
18#include <linux/init.h>
19#include <linux/timex.h>
20
21#include <asm/segment.h>
22#include <asm/io.h>
23#include <asm/irq.h>
24#include <asm/regs306x.h>
25
26#define CMFA 6
27
28#define CMIEA 0x40
29#define CCLR_CMA 0x08
30#define CLK_DIV8192 0x03
31
32#define H8300_TIMER_FREQ CONFIG_CPU_CLOCK*1000/8192 /* Timer input freq. */
33
34void __init platform_timer_setup(irqreturn_t (*timer_int)(int, void *, struct pt_regs *))
35{
36 /* setup 8bit timer ch2 */
37 ctrl_outb(H8300_TIMER_FREQ / HZ, TCORA2); /* set interval */
38 ctrl_outb(0x00, _8TCSR2); /* no output */
39 request_irq(40, timer_int, 0, "timer", 0);
40 ctrl_outb(CMIEA|CCLR_CMA|CLK_DIV8192, _8TCR2); /* start count */
41}
42
43void platform_timer_eoi(void)
44{
45 *(volatile unsigned char *)_8TCSR2 &= ~(1 << CMFA);
46}
47
48void platform_gettod(int *year, int *mon, int *day, int *hour,
49 int *min, int *sec)
50{
51 *year = *mon = *day = *hour = *min = *sec = 0;
52}
53
diff --git a/arch/h8300/platform/h8300h/ints_h8300h.c b/arch/h8300/platform/h8300h/ints_h8300h.c
new file mode 100644
index 000000000000..86a155479167
--- /dev/null
+++ b/arch/h8300/platform/h8300h/ints_h8300h.c
@@ -0,0 +1,86 @@
1/*
2 * linux/arch/h8300/platform/h8300h/ints_h8300h.c
3 * Interrupt handling CPU variants
4 *
5 * Yoshinori Sato <ysato@users.sourceforge.jp>
6 *
7 */
8
9#include <linux/config.h>
10#include <linux/init.h>
11#include <linux/errno.h>
12
13#include <asm/ptrace.h>
14#include <asm/traps.h>
15#include <asm/irq.h>
16#include <asm/io.h>
17#include <asm/gpio.h>
18#include <asm/regs306x.h>
19
20/* saved vector list */
21const int __initdata h8300_saved_vectors[]={
22#if defined(CONFIG_GDB_DEBUG)
23 TRAP3_VEC,
24#endif
25 -1
26};
27
28/* trap entry table */
29const unsigned long __initdata h8300_trap_table[NR_TRAPS]={
30 0,0,0,0,0,0,0,0,
31 (unsigned long)system_call, /* TRAPA #0 */
32 0,0,
33 (unsigned long)trace_break, /* TRAPA #3 */
34};
35
36int h8300_enable_irq_pin(unsigned int irq)
37{
38 int bitmask;
39 if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
40 return 0;
41
42 /* initialize IRQ pin */
43 bitmask = 1 << (irq - EXT_IRQ0);
44 switch(irq) {
45 case EXT_IRQ0:
46 case EXT_IRQ1:
47 case EXT_IRQ2:
48 case EXT_IRQ3:
49 if (H8300_GPIO_RESERVE(H8300_GPIO_P8, bitmask) == 0)
50 return -EBUSY;
51 H8300_GPIO_DDR(H8300_GPIO_P8, bitmask, H8300_GPIO_INPUT);
52 break;
53 case EXT_IRQ4:
54 case EXT_IRQ5:
55 if (H8300_GPIO_RESERVE(H8300_GPIO_P9, bitmask) == 0)
56 return -EBUSY;
57 H8300_GPIO_DDR(H8300_GPIO_P9, bitmask, H8300_GPIO_INPUT);
58 break;
59 }
60
61 return 0;
62}
63
64void h8300_disable_irq_pin(unsigned int irq)
65{
66 int bitmask;
67 if (irq < EXT_IRQ0 || irq > EXT_IRQ5)
68 return;
69
70 /* disable interrupt & release IRQ pin */
71 bitmask = 1 << (irq - EXT_IRQ0);
72 switch(irq) {
73 case EXT_IRQ0:
74 case EXT_IRQ1:
75 case EXT_IRQ2:
76 case EXT_IRQ3:
77 *(volatile unsigned char *)IER &= ~bitmask;
78 H8300_GPIO_FREE(H8300_GPIO_P8, bitmask);
79 break ;
80 case EXT_IRQ4:
81 case EXT_IRQ5:
82 *(volatile unsigned char *)IER &= ~bitmask;
83 H8300_GPIO_FREE(H8300_GPIO_P9, bitmask);
84 break;
85 }
86}
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
new file mode 100644
index 000000000000..18e51a7167d3
--- /dev/null
+++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c
@@ -0,0 +1,284 @@
1/*
2 * linux/arch/h8300/platform/h8300h/ptrace_h8300h.c
3 * ptrace cpu depend helper functions
4 *
5 * Yoshinori Sato <ysato@users.sourceforge.jp>
6 *
7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of
9 * this archive for more details.
10 */
11
12#include <linux/linkage.h>
13#include <linux/sched.h>
14#include <asm/ptrace.h>
15
16#define CCR_MASK 0x6f /* mode/imask not set */
17#define BREAKINST 0x5730 /* trapa #3 */
18
19/* Mapping from PT_xxx to the stack offset at which the register is
20 saved. Notice that usp has no stack-slot and needs to be treated
21 specially (see get_reg/put_reg below). */
22static const int h8300_register_offset[] = {
23 PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
24 PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
25 PT_REG(ccr), PT_REG(pc)
26};
27
28/* read register */
29long h8300_get_reg(struct task_struct *task, int regno)
30{
31 switch (regno) {
32 case PT_USP:
33 return task->thread.usp + sizeof(long)*2;
34 case PT_CCR:
35 return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
36 default:
37 return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
38 }
39}
40
41/* write register */
42int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
43{
44 unsigned short oldccr;
45 switch (regno) {
46 case PT_USP:
47 task->thread.usp = data - sizeof(long)*2;
48 case PT_CCR:
49 oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
50 oldccr &= ~CCR_MASK;
51 data &= CCR_MASK;
52 data |= oldccr;
53 *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
54 break;
55 default:
56 *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
57 break;
58 }
59 return 0;
60}
61
62/* disable singlestep */
63void h8300_disable_trace(struct task_struct *child)
64{
65 if((long)child->thread.breakinfo.addr != -1L) {
66 *child->thread.breakinfo.addr = child->thread.breakinfo.inst;
67 child->thread.breakinfo.addr = (unsigned short *)-1L;
68 }
69}
70
71/* calculate next pc */
72enum jump_type {none, /* normal instruction */
73 jabs, /* absolute address jump */
74 ind, /* indirect address jump */
75 ret, /* return to subrutine */
76 reg, /* register indexed jump */
77 relb, /* pc relative jump (byte offset) */
78 relw, /* pc relative jump (word offset) */
79 };
80
81/* opcode decode table define
82 ptn: opcode pattern
83 msk: opcode bitmask
84 len: instruction length (<0 next table index)
85 jmp: jump operation mode */
86struct optable {
87 unsigned char bitpattern;
88 unsigned char bitmask;
89 signed char length;
90 signed char type;
91} __attribute__((aligned(1),packed));
92
93#define OPTABLE(ptn,msk,len,jmp) \
94 { \
95 .bitpattern = ptn, \
96 .bitmask = msk, \
97 .length = len, \
98 .type = jmp, \
99 }
100
101const static struct optable optable_0[] = {
102 OPTABLE(0x00,0xff, 1,none), /* 0x00 */
103 OPTABLE(0x01,0xff,-1,none), /* 0x01 */
104 OPTABLE(0x02,0xfe, 1,none), /* 0x02-0x03 */
105 OPTABLE(0x04,0xee, 1,none), /* 0x04-0x05/0x14-0x15 */
106 OPTABLE(0x06,0xfe, 1,none), /* 0x06-0x07 */
107 OPTABLE(0x08,0xea, 1,none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */
108 OPTABLE(0x0a,0xee, 1,none), /* 0x0a-0x0b/0x1a-0x1b */
109 OPTABLE(0x0e,0xee, 1,none), /* 0x0e-0x0f/0x1e-0x1f */
110 OPTABLE(0x10,0xfc, 1,none), /* 0x10-0x13 */
111 OPTABLE(0x16,0xfe, 1,none), /* 0x16-0x17 */
112 OPTABLE(0x20,0xe0, 1,none), /* 0x20-0x3f */
113 OPTABLE(0x40,0xf0, 1,relb), /* 0x40-0x4f */
114 OPTABLE(0x50,0xfc, 1,none), /* 0x50-0x53 */
115 OPTABLE(0x54,0xfd, 1,ret ), /* 0x54/0x56 */
116 OPTABLE(0x55,0xff, 1,relb), /* 0x55 */
117 OPTABLE(0x57,0xff, 1,none), /* 0x57 */
118 OPTABLE(0x58,0xfb, 2,relw), /* 0x58/0x5c */
119 OPTABLE(0x59,0xfb, 1,reg ), /* 0x59/0x5b */
120 OPTABLE(0x5a,0xfb, 2,jabs), /* 0x5a/0x5e */
121 OPTABLE(0x5b,0xfb, 2,ind ), /* 0x5b/0x5f */
122 OPTABLE(0x60,0xe8, 1,none), /* 0x60-0x67/0x70-0x77 */
123 OPTABLE(0x68,0xfa, 1,none), /* 0x68-0x69/0x6c-0x6d */
124 OPTABLE(0x6a,0xfe,-2,none), /* 0x6a-0x6b */
125 OPTABLE(0x6e,0xfe, 2,none), /* 0x6e-0x6f */
126 OPTABLE(0x78,0xff, 4,none), /* 0x78 */
127 OPTABLE(0x79,0xff, 2,none), /* 0x79 */
128 OPTABLE(0x7a,0xff, 3,none), /* 0x7a */
129 OPTABLE(0x7b,0xff, 2,none), /* 0x7b */
130 OPTABLE(0x7c,0xfc, 2,none), /* 0x7c-0x7f */
131 OPTABLE(0x80,0x80, 1,none), /* 0x80-0xff */
132};
133
134const static struct optable optable_1[] = {
135 OPTABLE(0x00,0xff,-3,none), /* 0x0100 */
136 OPTABLE(0x40,0xf0,-3,none), /* 0x0140-0x14f */
137 OPTABLE(0x80,0xf0, 1,none), /* 0x0180-0x018f */
138 OPTABLE(0xc0,0xc0, 2,none), /* 0x01c0-0x01ff */
139};
140
141const static struct optable optable_2[] = {
142 OPTABLE(0x00,0x20, 2,none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */
143 OPTABLE(0x20,0x20, 3,none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */
144};
145
146const static struct optable optable_3[] = {
147 OPTABLE(0x69,0xfb, 2,none), /* 0x010069/0x01006d/014069/0x01406d */
148 OPTABLE(0x6b,0xff,-4,none), /* 0x01006b/0x01406b */
149 OPTABLE(0x6f,0xff, 3,none), /* 0x01006f/0x01406f */
150 OPTABLE(0x78,0xff, 5,none), /* 0x010078/0x014078 */
151};
152
153const static struct optable optable_4[] = {
154 OPTABLE(0x00,0x78, 3,none), /* 0x0100690?/0x01006d0?/0140690/0x01406d0?/0x0100698?/0x01006d8?/0140698?/0x01406d8? */
155 OPTABLE(0x20,0x78, 4,none), /* 0x0100692?/0x01006d2?/0140692/0x01406d2?/0x010069a?/0x01006da?/014069a?/0x01406da? */
156};
157
158const static struct optables_list {
159 const struct optable *ptr;
160 int size;
161} optables[] = {
162#define OPTABLES(no) \
163 { \
164 .ptr = optable_##no, \
165 .size = sizeof(optable_##no) / sizeof(struct optable), \
166 }
167 OPTABLES(0),
168 OPTABLES(1),
169 OPTABLES(2),
170 OPTABLES(3),
171 OPTABLES(4),
172
173};
174
175const unsigned char condmask[] = {
176 0x00,0x40,0x01,0x04,0x02,0x08,0x10,0x20
177};
178
179static int isbranch(struct task_struct *task,int reson)
180{
181 unsigned char cond = h8300_get_reg(task, PT_CCR);
182 /* encode complex conditions */
183 /* B4: N^V
184 B5: Z|(N^V)
185 B6: C|Z */
186 __asm__("bld #3,%w0\n\t"
187 "bxor #1,%w0\n\t"
188 "bst #4,%w0\n\t"
189 "bor #2,%w0\n\t"
190 "bst #5,%w0\n\t"
191 "bld #2,%w0\n\t"
192 "bor #0,%w0\n\t"
193 "bst #6,%w0\n\t"
194 :"=&r"(cond)::"cc");
195 cond &= condmask[reson >> 1];
196 if (!(reson & 1))
197 return cond == 0;
198 else
199 return cond != 0;
200}
201
202static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc)
203{
204 const struct optable *op;
205 unsigned char *fetch_p;
206 unsigned char inst;
207 unsigned long addr;
208 unsigned long *sp;
209 int op_len,regno;
210 op = optables[0].ptr;
211 op_len = optables[0].size;
212 fetch_p = (unsigned char *)pc;
213 inst = *fetch_p++;
214 do {
215 if ((inst & op->bitmask) == op->bitpattern) {
216 if (op->length < 0) {
217 op = optables[-op->length].ptr;
218 op_len = optables[-op->length].size + 1;
219 inst = *fetch_p++;
220 } else {
221 switch (op->type) {
222 case none:
223 return pc + op->length;
224 case jabs:
225 addr = *(unsigned long *)pc;
226 return (unsigned short *)(addr & 0x00ffffff);
227 case ind:
228 addr = *pc & 0xff;
229 return (unsigned short *)(*(unsigned long *)addr);
230 case ret:
231 sp = (unsigned long *)h8300_get_reg(child, PT_USP);
232 /* user stack frames
233 | er0 | temporary saved
234 +--------+
235 | exp | exception stack frames
236 +--------+
237 | ret pc | userspace return address
238 */
239 return (unsigned short *)(*(sp+2) & 0x00ffffff);
240 case reg:
241 regno = (*pc >> 4) & 0x07;
242 if (regno == 0)
243 addr = h8300_get_reg(child, PT_ER0);
244 else
245 addr = h8300_get_reg(child, regno-1+PT_ER1);
246 return (unsigned short *)addr;
247 case relb:
248 if ((inst = 0x55) || isbranch(child,inst & 0x0f))
249 pc = (unsigned short *)((unsigned long)pc +
250 ((signed char)(*fetch_p)));
251 return pc+1; /* skip myself */
252 case relw:
253 if ((inst = 0x5c) || isbranch(child,(*fetch_p & 0xf0) >> 4))
254 pc = (unsigned short *)((unsigned long)pc +
255 ((signed short)(*(pc+1))));
256 return pc+2; /* skip myself */
257 }
258 }
259 } else
260 op++;
261 } while(--op_len > 0);
262 return NULL;
263}
264
265/* Set breakpoint(s) to simulate a single step from the current PC. */
266
267void h8300_enable_trace(struct task_struct *child)
268{
269 unsigned short *nextpc;
270 nextpc = getnextpc(child,(unsigned short *)h8300_get_reg(child, PT_PC));
271 child->thread.breakinfo.addr = nextpc;
272 child->thread.breakinfo.inst = *nextpc;
273 *nextpc = BREAKINST;
274}
275
276asmlinkage void trace_trap(unsigned long bp)
277{
278 if ((unsigned long)current->thread.breakinfo.addr == bp) {
279 h8300_disable_trace(current);
280 force_sig(SIGTRAP,current);
281 } else
282 force_sig(SIGILL,current);
283}
284