tcg: fix size of local variables in tcg_gen_bswap64_i64
[qemu] / hw / mcf_intc.c
1 /*
2  * ColdFire Interrupt Controller emulation.
3  *
4  * Copyright (c) 2007 CodeSourcery.
5  *
6  * This code is licenced under the GPL
7  */
8 #include "hw.h"
9 #include "mcf.h"
10
11 typedef struct {
12     uint64_t ipr;
13     uint64_t imr;
14     uint64_t ifr;
15     uint64_t enabled;
16     uint8_t icr[64];
17     CPUState *env;
18     int active_vector;
19 } mcf_intc_state;
20
21 static void mcf_intc_update(mcf_intc_state *s)
22 {
23     uint64_t active;
24     int i;
25     int best;
26     int best_level;
27
28     active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
29     best_level = 0;
30     best = 64;
31     if (active) {
32         for (i = 0; i < 64; i++) {
33             if ((active & 1) != 0 && s->icr[i] >= best_level) {
34                 best_level = s->icr[i];
35                 best = i;
36             }
37             active >>= 1;
38         }
39     }
40     s->active_vector = ((best == 64) ? 24 : (best + 64));
41     m68k_set_irq_level(s->env, best_level, s->active_vector);
42 }
43
44 static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr)
45 {
46     int offset;
47     mcf_intc_state *s = (mcf_intc_state *)opaque;
48     offset = addr & 0xff;
49     if (offset >= 0x40 && offset < 0x80) {
50         return s->icr[offset - 0x40];
51     }
52     switch (offset) {
53     case 0x00:
54         return (uint32_t)(s->ipr >> 32);
55     case 0x04:
56         return (uint32_t)s->ipr;
57     case 0x08:
58         return (uint32_t)(s->imr >> 32);
59     case 0x0c:
60         return (uint32_t)s->imr;
61     case 0x10:
62         return (uint32_t)(s->ifr >> 32);
63     case 0x14:
64         return (uint32_t)s->ifr;
65     case 0xe0: /* SWIACK.  */
66         return s->active_vector;
67     case 0xe1: case 0xe2: case 0xe3: case 0xe4:
68     case 0xe5: case 0xe6: case 0xe7:
69         /* LnIACK */
70         hw_error("mcf_intc_read: LnIACK not implemented\n");
71     default:
72         return 0;
73     }
74 }
75
76 static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val)
77 {
78     int offset;
79     mcf_intc_state *s = (mcf_intc_state *)opaque;
80     offset = addr & 0xff;
81     if (offset >= 0x40 && offset < 0x80) {
82         int n = offset - 0x40;
83         s->icr[n] = val;
84         if (val == 0)
85             s->enabled &= ~(1ull << n);
86         else
87             s->enabled |= (1ull << n);
88         mcf_intc_update(s);
89         return;
90     }
91     switch (offset) {
92     case 0x00: case 0x04:
93         /* Ignore IPR writes.  */
94         return;
95     case 0x08:
96         s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
97         break;
98     case 0x0c:
99         s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
100         break;
101     default:
102         hw_error("mcf_intc_write: Bad write offset %d\n", offset);
103         break;
104     }
105     mcf_intc_update(s);
106 }
107
108 static void mcf_intc_set_irq(void *opaque, int irq, int level)
109 {
110     mcf_intc_state *s = (mcf_intc_state *)opaque;
111     if (irq >= 64)
112         return;
113     if (level)
114         s->ipr |= 1ull << irq;
115     else
116         s->ipr &= ~(1ull << irq);
117     mcf_intc_update(s);
118 }
119
120 static void mcf_intc_reset(mcf_intc_state *s)
121 {
122     s->imr = ~0ull;
123     s->ipr = 0;
124     s->ifr = 0;
125     s->enabled = 0;
126     memset(s->icr, 0, 64);
127     s->active_vector = 24;
128 }
129
130 static CPUReadMemoryFunc * const mcf_intc_readfn[] = {
131    mcf_intc_read,
132    mcf_intc_read,
133    mcf_intc_read
134 };
135
136 static CPUWriteMemoryFunc * const mcf_intc_writefn[] = {
137    mcf_intc_write,
138    mcf_intc_write,
139    mcf_intc_write
140 };
141
142 qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env)
143 {
144     mcf_intc_state *s;
145     int iomemtype;
146
147     s = qemu_mallocz(sizeof(mcf_intc_state));
148     s->env = env;
149     mcf_intc_reset(s);
150
151     iomemtype = cpu_register_io_memory(mcf_intc_readfn,
152                                        mcf_intc_writefn, s);
153     cpu_register_physical_memory(base, 0x100, iomemtype);
154
155     return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
156 }