• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revision6db1bc8e2ccef9bb8f9831cbd36674e404e845f7 (tree)
Time2019-01-01 23:53:15
AuthorYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Log Message

Add ms7619se support.

Change Summary

Incremental Difference

--- a/configure
+++ b/configure
@@ -7020,7 +7020,7 @@ target_name=$(echo $target | cut -d '-' -f 1)
70207020 target_bigendian="no"
70217021
70227022 case "$target_name" in
7023- armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
7023+ armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppc64|ppc64abi32|s390x|sh2|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
70247024 target_bigendian=yes
70257025 ;;
70267026 esac
@@ -7185,6 +7185,11 @@ case "$target_name" in
71857185 mttcg=yes
71867186 target_compiler=$cross_cc_riscv64
71877187 ;;
7188+ sh2)
7189+ TARGET_ARCH=sh4
7190+ bflt="yes"
7191+ target_compiler=$cross_cc_sh4
7192+ ;;
71887193 sh4|sh4eb)
71897194 TARGET_ARCH=sh4
71907195 bflt="yes"
@@ -7408,7 +7413,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
74087413 s390*)
74097414 disas_config "S390"
74107415 ;;
7411- sh4)
7416+ sh*)
74127417 disas_config "SH4"
74137418 ;;
74147419 sparc*)
--- /dev/null
+++ b/default-configs/sh2-softmmu.mak
@@ -0,0 +1,22 @@
1+# Default configuration for sh2-softmmu
2+
3+include pci.mak
4+include usb.mak
5+CONFIG_SERIAL=y
6+CONFIG_SERIAL_ISA=y
7+CONFIG_PTIMER=y
8+CONFIG_PFLASH_CFI02=y
9+CONFIG_SH4=y
10+CONFIG_IDE_MMIO=y
11+CONFIG_SM501=y
12+CONFIG_I2C=y
13+CONFIG_DDC=y
14+CONFIG_ISA_TESTDEV=y
15+CONFIG_I82378=y
16+CONFIG_I8259=y
17+CONFIG_I8254=y
18+CONFIG_PCSPK=y
19+CONFIG_I82374=y
20+CONFIG_I8257=y
21+CONFIG_MC146818RTC=y
22+CONFIG_RENESAS_CMT=y
--- a/hw/char/sh_serial.c
+++ b/hw/char/sh_serial.c
@@ -401,16 +401,21 @@ void sh_serial_init(MemoryRegion *sysmem,
401401
402402 sh_serial_clear_fifo(s);
403403
404- memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
405- "serial", 0x100000000ULL);
406-
407- memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem,
408- 0, 0x28);
409- memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
410-
411- memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem,
412- 0, 0x28);
413- memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
404+ if (base < 0xf0000000) {
405+ memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
406+ "serial", 0x100000000ULL);
407+
408+ memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem,
409+ 0, 0x28);
410+ memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4);
411+ memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem,
412+ 0, 0x28);
413+ memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
414+ } else {
415+ memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s,
416+ "serial", 0x10000);
417+ memory_region_add_subregion(sysmem, base, &s->iomem);
418+ }
414419
415420 if (chr) {
416421 qemu_chr_fe_init(&s->chr, chr, &error_abort);
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -33,7 +33,7 @@ obj-$(CONFIG_IOAPIC) += ioapic.o
3333 obj-$(CONFIG_OMAP) += omap_intc.o
3434 obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
3535 obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
36-obj-$(CONFIG_SH4) += sh_intc.o
36+obj-$(CONFIG_SH4) += sh_intc.o sh7619_intc.o
3737 obj-$(CONFIG_XICS) += xics.o
3838 obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
3939 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
--- /dev/null
+++ b/hw/intc/sh7619_intc.c
@@ -0,0 +1,351 @@
1+/*
2+ * SH7619 Interrupt controller
3+ *
4+ * Copyright (c) 2018 Yoshinori Sato
5+ *
6+ * This code is licensed under the GPL.
7+ */
8+
9+#include "qemu/osdep.h"
10+#include "qemu-common.h"
11+#include "cpu.h"
12+#include "hw/hw.h"
13+#include "hw/sysbus.h"
14+#include "hw/sh4/sh_intc.h"
15+#include "hw/intc/sh7619intc.h"
16+#include "qemu/error-report.h"
17+
18+static void sh7619intc_set_irq(void *opaque, int n_IRQ, int level)
19+{
20+ SH7619INTCState *intc = opaque;
21+ struct IRQSource *src;
22+ int issue = 0;
23+
24+ n_IRQ += 64;
25+ if (n_IRQ < 64 || n_IRQ >= 128) {
26+ error_report("%s: IRQ %d out of range", __func__, n_IRQ);
27+ return;
28+ }
29+
30+ src = &intc->src[n_IRQ - 64];
31+
32+ level = (level != 0);
33+ if (n_IRQ >= 64 && n_IRQ <= 71) {
34+ if (level)
35+ intc->irqsr |= (0x100 << (n_IRQ - 64));
36+ else
37+ intc->irqsr &= ~(0x100 << (n_IRQ - 64));
38+ }
39+ switch (src->sense) {
40+ case TRG_LEVEL:
41+ /* level-sensitive irq */
42+ issue = (level == 0);
43+ break;
44+ case TRG_NEDGE:
45+ issue = (level == 0 && src->level == 1);
46+ break;
47+ case TRG_PEDGE:
48+ issue = (level == 1 && src->level == 0);
49+ break;
50+ case TRG_BEDGE:
51+ issue = ((level ^ src->level) & 1);
52+ break;
53+ }
54+ src->level = level;
55+ if (issue == 0 && src->sense == TRG_LEVEL) {
56+ if (n_IRQ >= 64 && n_IRQ <= 71)
57+ intc->irqsr &= ~(1 << (n_IRQ - 64));
58+ if (intc->req_irq == n_IRQ) {
59+ qemu_set_irq(intc->irq, 0);
60+ src->req = 0;
61+ intc->req_irq = -1;
62+ }
63+ return;
64+ }
65+ if (issue) {
66+ if (n_IRQ >= 64 && n_IRQ <= 71)
67+ intc->irqsr |= (1 << (n_IRQ - 64));
68+ src->req = 1;
69+ if(intc->req_irq < 0) {
70+ qemu_set_irq(intc->irq, 1);
71+ intc->req_irq = n_IRQ;
72+ }
73+ }
74+}
75+
76+static int priority(SH7619INTCState *intc, int req)
77+{
78+ static const int map[] = {
79+ 3, 2, 1, 0, -1, -1, -1, -1,
80+ -1, -1, -1, -1, -1, -1, -1, -1,
81+ 7, 6, 5, 4, 11, 10, 9, 8,
82+ 15, 15, 15, 15, 14, 14, 14, 14,
83+ 13, 13, 13, 13, 19, 18, -1, -1,
84+ 23, 22, 21, 20, 27, -1, -1, -1,
85+ -1, -1, -1, -1, -1, -1, -1, -1,
86+ -1, -1, -1, -1, -1, -1, -1, -1,
87+ };
88+ int offset;
89+ int pos;
90+ offset = map[req - 64] / 4;
91+ pos = map[req - 64] % 4;
92+ return (intc->ipr[offset] >> pos) & 0x000f;
93+}
94+
95+int sh2_intc_get_pending_vector(void *state, int imask, int *level)
96+{
97+ SH7619INTCState *intc = SH7619INTC(state);
98+ int pri = priority(intc, intc->req_irq);
99+ int ret = -1;
100+ int i;
101+ int pend;
102+
103+ if (pri > imask) {
104+ *level = pri;
105+ ret = intc->req_irq;
106+ intc->src[intc->req_irq - 64].req = 0;
107+ intc->req_irq = -1;
108+ }
109+ pri = -1;
110+ pend = -1;
111+ for (i = 0; i < 64; i++) {
112+ if (intc->src[i].req && pri < priority(intc, i + 64)) {
113+ pri = priority(intc, i + 64);
114+ pend = i + 64;
115+ }
116+ }
117+ if (pend >= 0) {
118+ qemu_set_irq(intc->irq, 1);
119+ intc->req_irq = pend;
120+ }
121+ return ret;
122+}
123+
124+static void intc_write1(void *opaque, hwaddr addr, uint64_t val, unsigned size)
125+{
126+ int reg = (addr & 0x0f) >> 1;
127+ SH7619INTCState *intc = SH7619INTC(opaque);
128+
129+ if (reg < 5)
130+ intc->ipr[reg + 2] = val;
131+ else
132+ error_report("sh7619intc: unsupported write request at %08lx", addr);
133+}
134+
135+static uint64_t intc_read1(void *opaque, hwaddr addr, unsigned size)
136+{
137+ int reg = (addr & 0x0f) >> 1;
138+ SH7619INTCState *intc = SH7619INTC(opaque);
139+
140+ if (reg < 5)
141+ return intc->ipr[reg + 2];
142+ else {
143+ error_report("sh7619intc: unsupported write request at %08lx", addr);
144+ return 0;
145+ }
146+}
147+
148+static void update_byte(unsigned int *word, uint64_t val, int pos)
149+{
150+ *word &= 0xff << (pos * 8);
151+ *word |= (val & 0xff) << ((1 - pos) * 8);
152+}
153+
154+static void write_irqsr(SH7619INTCState *intc, uint64_t val)
155+{
156+ int mask = ~intc->read_sr;
157+ intc->irqsr &= mask;
158+ intc->irqsr |= val & 0xff;
159+}
160+
161+static void update_trigger(SH7619INTCState *intc)
162+{
163+ int i;
164+ for (i = 0; i < 8; i++) {
165+ intc->src[i].sense = (intc->irqcr >> (i * 2)) & 3;
166+ }
167+}
168+
169+static void intc_write2(void *opaque, hwaddr addr, uint64_t val, unsigned size)
170+{
171+ SH7619INTCState *intc = SH7619INTC(opaque);
172+ int error = 0;
173+
174+ if (size == 2) {
175+ switch (addr & 0x0f) {
176+ case 0: /* ICR0 */
177+ intc->icr0 &= ~0x80;
178+ intc->icr0 |= val & 0x80;
179+ break;
180+ case 2: /* IRQCR */
181+ intc->irqcr = val;
182+ update_trigger(intc);
183+ break;
184+ case 4:
185+ write_irqsr(intc, val);
186+ break;
187+ case 6: /* IPR */
188+ case 8:
189+ intc->ipr[((addr & 0x0f) - 8) / 2] = val;
190+ break;
191+ default:
192+ error=1;
193+ break;
194+ }
195+ } else {
196+ switch (addr & 0x0f) {
197+ case 1: /* ICR0 */
198+ intc->icr0 &= ~0x80;
199+ intc->icr0 |= val & 0x80;
200+ break;
201+ case 2 ... 3: /* IRQCR */
202+ update_byte(&intc->irqcr, val, addr & 1);
203+ update_trigger(intc);
204+ break;
205+ case 5: /* IRQSR */
206+ write_irqsr(intc, val);
207+ break;
208+ case 6 ... 9: /* IPR */
209+ update_byte(&intc->ipr[((addr & 0x0f) - 8) / 2], val, addr & 1);
210+ break;
211+ default:
212+ error = 1;
213+ }
214+ }
215+ if (error)
216+ error_report("sh7619intc: unsupported write request at %08lx", addr);
217+}
218+
219+static unsigned int read_byte(unsigned int val, int pos)
220+{
221+ return (val >> ((1 - pos) * 8)) & 0xff;
222+}
223+
224+static uint64_t intc_read2(void *opaque, hwaddr addr, unsigned size)
225+{
226+ SH7619INTCState *intc = SH7619INTC(opaque);
227+ int error = 0;
228+
229+ if (size == 2) {
230+ switch (addr & 0x0f) {
231+ case 0: /* ICR0 */
232+ return intc->icr0;
233+ break;
234+ case 2: /* IRQCR */
235+ return intc->irqcr;
236+ break;
237+ case 4: /* IRQSR */
238+ intc->read_sr = intc->irqsr & 0xff;
239+ return intc->irqsr;
240+ break;
241+ case 6: /* IPR */
242+ case 8:
243+ return intc->ipr[((addr & 0x0f) - 8) / 2];
244+ break;
245+ default:
246+ error=1;
247+ break;
248+ }
249+ } else {
250+ switch (addr & 0x0f) {
251+ case 0 ... 1: /* ICR0 */
252+ return read_byte(intc->icr0, addr & 1);
253+ break;
254+ case 2 ... 3: /* IRQCR */
255+ return read_byte(intc->irqcr, addr & 1);
256+ break;
257+ case 4 ... 5: /* IRQCR */
258+ if (addr & 1)
259+ intc->read_sr = intc->irqsr & 0xff;
260+ return read_byte(intc->irqsr, addr & 1);
261+ break;
262+ case 6 ... 9: /* IPR */
263+ return read_byte(intc->ipr[((addr & 0x0f) - 8) / 2], addr & 1);
264+ break;
265+ default:
266+ error = 1;
267+ }
268+ }
269+ if (error)
270+ error_report("sh7619intc: unsupported write request at %08lx", addr);
271+ return -1;
272+}
273+
274+static const MemoryRegionOps intc_ops1 = {
275+ .write = intc_write1,
276+ .read = intc_read1,
277+ .endianness = DEVICE_BIG_ENDIAN,
278+ .impl = {
279+ .min_access_size = 2,
280+ .max_access_size = 2,
281+ },
282+};
283+
284+static const MemoryRegionOps intc_ops2 = {
285+ .write = intc_write2,
286+ .read = intc_read2,
287+ .endianness = DEVICE_BIG_ENDIAN,
288+ .impl = {
289+ .min_access_size = 1,
290+ .max_access_size = 2,
291+ },
292+};
293+
294+static void sh7619intc_realize(DeviceState *dev, Error **errp)
295+{
296+ SH7619INTCState *intc = SH7619INTC(dev);
297+ int i;
298+
299+ for (i = 0; i < 64; i++) {
300+ intc->src[i].sense = TRG_PEDGE;
301+ }
302+ intc->req_irq = -1;
303+}
304+
305+static void sh7619intc_init(Object *obj)
306+{
307+ SysBusDevice *d = SYS_BUS_DEVICE(obj);
308+ SH7619INTCState *intc = SH7619INTC(obj);
309+
310+ memory_region_init_io(&intc->memory[0], OBJECT(intc), &intc_ops1,
311+ intc, "sh7619-intc-1", 0x10);
312+ memory_region_init_io(&intc->memory[1], OBJECT(intc), &intc_ops2,
313+ intc, "sh7619-intc-2", 0x10);
314+ sysbus_init_mmio(d, &intc->memory[0]);
315+ sysbus_init_mmio(d, &intc->memory[1]);
316+
317+ qdev_init_gpio_in(DEVICE(d), sh7619intc_set_irq, 64);
318+ sysbus_init_irq(d, &intc->irq);
319+}
320+
321+static const VMStateDescription vmstate_sh7619intc = {
322+ .name = "sh7619-intc",
323+ .version_id = 1,
324+ .minimum_version_id = 1,
325+ .fields = (VMStateField[]) {
326+ VMSTATE_END_OF_LIST()
327+ }
328+};
329+
330+static void sh7619intc_class_init(ObjectClass *klass, void *data)
331+{
332+ DeviceClass *dc = DEVICE_CLASS(klass);
333+
334+ dc->realize = sh7619intc_realize;
335+ dc->vmsd = &vmstate_sh7619intc;
336+}
337+
338+static const TypeInfo sh7619intc_info = {
339+ .name = TYPE_SH7619INTC,
340+ .parent = TYPE_SYS_BUS_DEVICE,
341+ .instance_size = sizeof(SH7619INTCState),
342+ .instance_init = sh7619intc_init,
343+ .class_init = sh7619intc_class_init,
344+};
345+
346+static void sh7619intc_register_types(void)
347+{
348+ type_register_static(&sh7619intc_info);
349+}
350+
351+type_init(sh7619intc_register_types)
--- a/hw/sh4/Makefile.objs
+++ b/hw/sh4/Makefile.objs
@@ -1,4 +1,5 @@
1-obj-y += shix.o r2d.o
1+obj-y += shix.o r2d.o ms7619se.o
22
33 obj-y += sh7750.o sh7750_regnames.o
44 obj-y += sh_pci.o
5+obj-y += sh7619.o
\ No newline at end of file
--- /dev/null
+++ b/hw/sh4/ms7619se.c
@@ -0,0 +1,157 @@
1+/*
2+ * SolutionEngine MS7619SE emulation
3+ *
4+ * Copyright (c) 2018 Yoshinori Sato
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+ * THE SOFTWARE.
23+ */
24+
25+#include "qemu/osdep.h"
26+#include "qemu/units.h"
27+#include "qapi/error.h"
28+#include "qemu-common.h"
29+#include "cpu.h"
30+#include "hw/hw.h"
31+#include "hw/sysbus.h"
32+#include "hw/loader.h"
33+#include "hw/sh4/sh7619.h"
34+#include "sysemu/sysemu.h"
35+#include "sysemu/qtest.h"
36+#include "sysemu/device_tree.h"
37+#include "hw/boards.h"
38+#include "hw/block/flash.h"
39+#include "exec/address-spaces.h"
40+#include "exec/cpu-all.h"
41+
42+#define FLASH_BASE 0x00000000
43+#define FLASH_SIZE 0x02000000
44+
45+#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
46+#define SDRAM_SIZE 0x04000000
47+
48+#define BOOT_PARAMS_OFFSET 0x0001000
49+/* CONFIG_BOOT_LINK_OFFSET of Linux kernel */
50+#define LINUX_LOAD_OFFSET 0x0800000
51+#define INITRD_LOAD_OFFSET 0x1800000
52+
53+static struct QEMU_PACKED
54+{
55+ int mount_root_rdonly;
56+ int ramdisk_flags;
57+ int orig_root_dev;
58+ int loader_type;
59+ int initrd_start;
60+ int initrd_size;
61+
62+ char pad[232];
63+
64+ char kernel_cmdline[256];
65+} boot_params;
66+
67+static void ms7619se_init(MachineState *machine)
68+{
69+ SuperHCPU *cpu;
70+ SH7619State *s;
71+ MemoryRegion *sysmem = get_system_memory();
72+ MemoryRegion *sdram = g_new(MemoryRegion, 1);
73+ DriveInfo *dinfo;
74+ const char *kernel_filename = machine->kernel_filename;
75+ const char *kernel_cmdline = machine->kernel_cmdline;
76+ const char *initrd_filename = machine->initrd_filename;
77+
78+ /* Allocate memory space */
79+ memory_region_init_ram(sdram, NULL, "ms7619se.sdram", 0x04000000,
80+ &error_fatal);
81+ memory_region_add_subregion(sysmem, 0x0c000000, sdram);
82+ dinfo = drive_get(IF_PFLASH, 0, 0);
83+ pflash_cfi02_register(0x0, NULL, "ms7619se.flash", FLASH_SIZE,
84+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
85+ 16 * KiB, FLASH_SIZE >> 16,
86+ 1, 4, 0x0000, 0x0000, 0x0000, 0x0000,
87+ 0x555, 0x2aa, 0);
88+
89+ cpu = SUPERH_CPU(cpu_create(machine->cpu_type));
90+ s = sh7619_init(cpu, sysmem);
91+
92+ memset(&boot_params, 0, sizeof(boot_params));
93+
94+ if (kernel_filename) {
95+ int kernel_size;
96+
97+ kernel_size = load_image_targphys(kernel_filename,
98+ SDRAM_BASE + LINUX_LOAD_OFFSET,
99+ INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET);
100+ if (kernel_size < 0) {
101+ fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
102+ exit(1);
103+ }
104+ cpu->env.pc = 0x80000000 + SDRAM_BASE + LINUX_LOAD_OFFSET;
105+ s->frqcr = 0x1103;
106+ }
107+
108+ if (initrd_filename) {
109+ int initrd_size;
110+
111+ initrd_size = load_image_targphys(initrd_filename,
112+ SDRAM_BASE + INITRD_LOAD_OFFSET,
113+ SDRAM_SIZE - INITRD_LOAD_OFFSET);
114+
115+ if (initrd_size < 0) {
116+ fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename);
117+ exit(1);
118+ }
119+
120+ /* initialization which should be done by firmware */
121+ boot_params.loader_type = tswap32(1);
122+ boot_params.initrd_start = tswap32(INITRD_LOAD_OFFSET);
123+ boot_params.initrd_size = tswap32(initrd_size);
124+ }
125+
126+ if (kernel_cmdline) {
127+ /* I see no evidence that this .kernel_cmdline buffer requires
128+ NUL-termination, so using strncpy should be ok. */
129+ strncpy(boot_params.kernel_cmdline, kernel_cmdline,
130+ sizeof(boot_params.kernel_cmdline));
131+ }
132+
133+ rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params),
134+ SDRAM_BASE + BOOT_PARAMS_OFFSET);
135+}
136+
137+static void ms7619se_class_init(ObjectClass *oc, void *data)
138+{
139+ MachineClass *mc = MACHINE_CLASS(oc);
140+
141+ mc->desc = "MS7619SE";
142+ mc->init = ms7619se_init;
143+ mc->default_cpu_type = TYPE_SH7619_CPU;
144+}
145+
146+static const TypeInfo ms7619se_type = {
147+ .name = MACHINE_TYPE_NAME("ms7619se"),
148+ .parent = TYPE_MACHINE,
149+ .class_init = ms7619se_class_init,
150+};
151+
152+static void ms7619se_machine_init(void)
153+{
154+ type_register_static(&ms7619se_type);
155+}
156+
157+type_init(ms7619se_machine_init)
--- /dev/null
+++ b/hw/sh4/sh7619.c
@@ -0,0 +1,171 @@
1+/*
2+ * SH7619 device
3+ *
4+ * Copyright (c) 2018 Yoshinori Sato
5+ *
6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7+ * of this software and associated documentation files (the "Software"), to deal
8+ * in the Software without restriction, including without limitation the rights
9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ * copies of the Software, and to permit persons to whom the Software is
11+ * furnished to do so, subject to the following conditions:
12+ *
13+ * The above copyright notice and this permission notice shall be included in
14+ * all copies or substantial portions of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+ * THE SOFTWARE.
23+ */
24+#include "qemu/osdep.h"
25+#include "qapi/error.h"
26+#include "hw/hw.h"
27+#include "hw/sh4/sh7619.h"
28+#include "sysemu/sysemu.h"
29+#include "hw/loader.h"
30+#include "hw/intc/sh7619intc.h"
31+#include "hw/timer/renesas_cmt.h"
32+#include "cpu.h"
33+#include "exec/exec-all.h"
34+
35+#define SCIF0_ERI (88 - 64)
36+#define SCIF0_RXI (89 - 64)
37+#define SCIF0_BRI (90 - 64)
38+#define SCIF0_TXI (91 - 64)
39+#define SCIF1_ERI (92 - 64)
40+#define SCIF1_RXI (93 - 64)
41+#define SCIF1_BRI (94 - 64)
42+#define SCIF1_TXI (95 - 64)
43+#define SCIF2_ERI (96 - 64)
44+#define SCIF2_RXI (97 - 64)
45+#define SCIF2_BRI (98 - 64)
46+#define SCIF2_TXI (99 - 64)
47+
48+static void sh7619_set_irq(void *opaque, int no, int request)
49+{
50+ SuperHCPU *cpu = SUPERH_CPU(opaque);
51+ CPUState *cs = CPU(cpu);
52+ if (request)
53+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
54+ else
55+ cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
56+}
57+
58+static SH7619INTCState *register_intc(SH7619State *s)
59+{
60+ SysBusDevice *intc;
61+ int i;
62+
63+ intc = SYS_BUS_DEVICE(qdev_create(NULL, TYPE_SH7619INTC));
64+ sysbus_mmio_map(intc, 0, 0xf8080000);
65+ sysbus_mmio_map(intc, 1, 0xf8140000);
66+ for (i = 0; i < 64; i++)
67+ s->irq[i] = qdev_get_gpio_in(DEVICE(intc), i);
68+
69+ qdev_init_nofail(DEVICE(intc));
70+ sysbus_connect_irq(SYS_BUS_DEVICE(intc), 0,
71+ qdev_get_gpio_in(DEVICE(s->cpu), 0));
72+
73+ return SH7619INTC(intc);
74+}
75+
76+static RCMTState *register_cmt(SH7619State *s)
77+{
78+ SysBusDevice *cmt;
79+ int i;
80+
81+ cmt = SYS_BUS_DEVICE(qdev_create(NULL, TYPE_RCMT));
82+ sysbus_mmio_map(cmt, 0, 0xf84a0070);
83+ qdev_prop_set_uint64(DEVICE(cmt), "input-freq", 31250000);
84+
85+ qdev_init_nofail(DEVICE(cmt));
86+ for (i = 0; i < 2; i++)
87+ sysbus_connect_irq(cmt, i, s->irq[(86 + i) - 64]);
88+
89+ return RCMT(cmt);
90+}
91+
92+static void cache_write(void *opaque, hwaddr addr,
93+ uint64_t mem_value, unsigned size)
94+{
95+}
96+
97+static uint64_t cache_read(void *opaque, hwaddr addr,
98+ unsigned size)
99+{
100+ return 0;
101+}
102+
103+
104+static const MemoryRegionOps cache_ops = {
105+ .read = cache_read,
106+ .write = cache_write,
107+ .endianness = DEVICE_BIG_ENDIAN,
108+};
109+
110+static void cpg_write(void *opaque, hwaddr addr,
111+ uint64_t mem_value, unsigned size)
112+{
113+ SH7619State *s = opaque;
114+ s->frqcr = mem_value;
115+}
116+
117+static uint64_t cpg_read(void *opaque, hwaddr addr,
118+ unsigned size)
119+{
120+ SH7619State *s = opaque;
121+ return s->frqcr;
122+}
123+
124+
125+static const MemoryRegionOps cpg_ops = {
126+ .read = cpg_read,
127+ .write = cpg_write,
128+ .endianness = DEVICE_BIG_ENDIAN,
129+ .impl = {
130+ .min_access_size = 2,
131+ .max_access_size = 2,
132+ },
133+};
134+
135+#define SCIF(no) \
136+ sh_serial_init(s->sysmem, 0xf8400000 + no * 0x00010000, \
137+ SH_SERIAL_FEAT_SCIF, \
138+ 31250000, serial_hd(no), \
139+ s->irq[SCIF ## no ## _ERI], \
140+ s->irq[SCIF ## no ## _RXI], \
141+ s->irq[SCIF ## no ## _TXI], \
142+ NULL, \
143+ s->irq[SCIF ## no ## _BRI])
144+
145+SH7619State *sh7619_init(SuperHCPU *cpu, MemoryRegion *sysmem)
146+{
147+ SH7619State *s;
148+
149+ s = g_malloc0(sizeof(SH7619State));
150+ s->cpu = cpu;
151+ s->sysmem = sysmem;
152+
153+ memory_region_init_io(&s->cache, NULL, &cache_ops,
154+ NULL, "cache", 0x02000000);
155+ memory_region_add_subregion(s->sysmem, 0xf0000000, &s->cache);
156+ memory_region_init_io(&s->cpg, NULL, &cpg_ops,
157+ s, "cpg", 0x00000002);
158+ memory_region_add_subregion(s->sysmem, 0xf815ff80, &s->cpg);
159+ memory_region_init_ram(&s->uram, NULL, "uram", 0x4000, NULL);
160+ memory_region_add_subregion(s->sysmem, 0xe55fc000, &s->uram);
161+
162+ qdev_init_gpio_in(DEVICE(cpu), sh7619_set_irq, 1);
163+ s->intc = register_intc(s);
164+ s->cpu->env.intc_handle = s->intc;
165+ register_cmt(s);
166+ SCIF(0);
167+ SCIF(1);
168+ SCIF(2);
169+
170+ return s;
171+}
--- a/hw/timer/Makefile.objs
+++ b/hw/timer/Makefile.objs
@@ -32,6 +32,7 @@ obj-$(CONFIG_OMAP) += omap_gptimer.o
3232 obj-$(CONFIG_OMAP) += omap_synctimer.o
3333 obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o
3434 obj-$(CONFIG_SH4) += sh_timer.o
35+obj-$(CONFIG_RENESAS_CMT) += renesas_cmt.o
3536 obj-$(CONFIG_DIGIC) += digic-timer.o
3637 obj-$(CONFIG_MIPS_CPS) += mips_gictimer.o
3738
--- /dev/null
+++ b/hw/timer/renesas_cmt.c
@@ -0,0 +1,218 @@
1+/*
2+ * Renesas Compare-match timer
3+ *
4+ * Copyright (c) 2018 Yoshinori Sato
5+ *
6+ * This code is licensed under the GPL version 2 or later.
7+ *
8+ */
9+
10+#include "qemu/osdep.h"
11+#include "qemu-common.h"
12+#include "qemu/timer.h"
13+#include "cpu.h"
14+#include "hw/hw.h"
15+#include "hw/sysbus.h"
16+#include "hw/timer/renesas_cmt.h"
17+#include "qemu/error-report.h"
18+
19+#define freq_to_ns(freq) (1000000000LL / freq)
20+static const int clkdiv[] = {8,32,128,512};
21+
22+static void update_events(RCMTState *cmt, int ch)
23+{
24+ uint16_t diff;
25+
26+ if ((cmt->cmstr & (1 << ch))== 0)
27+ return ;
28+ diff = cmt->cmcor[ch] - cmt->cmcnt[ch];
29+ timer_mod(cmt->timer[ch],
30+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
31+ diff * freq_to_ns(cmt->input_freq) *
32+ clkdiv[cmt->cmcr[ch] & 3]);
33+}
34+
35+static uint64_t read_cmcnt(RCMTState *cmt, int ch)
36+{
37+ int64_t delta, now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
38+
39+ if (cmt->cmstr & (1 << ch)) {
40+ delta = (now - cmt->tick[ch]) / freq_to_ns(cmt->input_freq);
41+ delta /= clkdiv[cmt->cmcr[ch] & 0x03];
42+ return cmt->cmcnt[ch] + delta;
43+ } else
44+ return cmt->cmcnt[ch];
45+}
46+
47+static uint64_t cmt_read(void *opaque, hwaddr addr, unsigned size)
48+{
49+ hwaddr offset = addr & 0x0f;
50+ RCMTState *cmt = opaque;
51+ int ch = offset / 0x08;
52+ int error = 1;
53+
54+ if (offset == 0) {
55+ return cmt->cmstr;
56+ error = 0;
57+ } else {
58+ offset &= 0x07;
59+ if (ch == 0)
60+ offset -= 0x02;
61+ error = 0;
62+ switch(offset) {
63+ case 0:
64+ return cmt->cmcr[ch];
65+ case 2:
66+ return read_cmcnt(cmt, ch);
67+ case 4:
68+ return cmt->cmcor[ch];
69+ default:
70+ error = 1;
71+ }
72+ }
73+ if (error)
74+ error_report("rcmt: unsupported read request to %08lx", addr);
75+ return 0xffffffffffffffffUL;
76+}
77+
78+static void start_stop(RCMTState *cmt, int ch, int st)
79+{
80+ if (st)
81+ update_events(cmt, ch);
82+ else
83+ timer_del(cmt->timer[ch]);
84+}
85+
86+static void cmt_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
87+{
88+ hwaddr offset = addr & 0x0f;
89+ RCMTState *cmt = opaque;
90+ int ch = offset / 0x08;
91+ int error = 1;
92+
93+ if (offset == 0) {
94+ cmt->cmstr = val;
95+ start_stop(cmt, 0, cmt->cmstr & 1);
96+ start_stop(cmt, 1, (cmt->cmstr >> 1) & 1);
97+ error = 0;
98+ } else {
99+ offset &= 0x07;
100+ if (ch == 0)
101+ offset -= 0x02;
102+ error = 0;
103+ switch(offset) {
104+ case 0:
105+ cmt->cmcr[ch] = val;
106+ break;
107+ case 2:
108+ cmt->cmcnt[ch] = val;
109+ break;
110+ case 4:
111+ cmt->cmcor[ch] = val;
112+ break;
113+ default:
114+ error = 1;
115+ }
116+ if (error == 0 && cmt->cmstr & (1 << ch))
117+ update_events(cmt, ch);
118+ }
119+ if (error)
120+ error_report("rcmt: unsupported write request to %08lx", addr);
121+}
122+
123+static const MemoryRegionOps cmt_ops = {
124+ .write = cmt_write,
125+ .read = cmt_read,
126+ .endianness = DEVICE_NATIVE_ENDIAN,
127+ .impl = {
128+ .min_access_size = 2,
129+ .max_access_size = 2,
130+ },
131+};
132+
133+static void timer_events(RCMTState *cmt, int ch)
134+{
135+ cmt->cmcnt[ch] = 0;
136+ cmt->tick[ch] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
137+ update_events(cmt, ch);
138+ if (cmt->cmcr[ch] & 0x40)
139+ qemu_irq_pulse(cmt->cmi[ch]);
140+}
141+
142+static void timer_event0(void *opaque)
143+{
144+ RCMTState *cmt = opaque;
145+
146+ timer_events(cmt, 0);
147+}
148+
149+static void timer_event1(void *opaque)
150+{
151+ RCMTState *cmt = opaque;
152+
153+ timer_events(cmt, 1);
154+}
155+
156+static void rcmt_reset(DeviceState *dev)
157+{
158+ RCMTState *cmt = RCMT(dev);
159+ cmt->cmstr = 0;
160+ cmt->cmcr[0] = cmt->cmcr[1] = 0;
161+ cmt->cmcnt[0] = cmt->cmcnt[1] = 0;
162+ cmt->cmcor[0] = cmt->cmcor[1] = 0xffff;
163+}
164+
165+static void rcmt_init(Object *obj)
166+{
167+ SysBusDevice *d = SYS_BUS_DEVICE(obj);
168+ RCMTState *cmt = RCMT(obj);
169+ int i;
170+
171+ memory_region_init_io(&cmt->memory, OBJECT(cmt), &cmt_ops,
172+ cmt, "renesas-cmt", 0x10);
173+ sysbus_init_mmio(d, &cmt->memory);
174+
175+ for (i = 0; i < 2; i++) {
176+ sysbus_init_irq(d, &cmt->cmi[i]);
177+ }
178+ cmt->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event0, cmt);
179+ cmt->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, timer_event1, cmt);
180+}
181+
182+static const VMStateDescription vmstate_rcmt = {
183+ .name = "rx-cmt",
184+ .version_id = 1,
185+ .minimum_version_id = 1,
186+ .fields = (VMStateField[]) {
187+ VMSTATE_END_OF_LIST()
188+ }
189+};
190+
191+static Property rcmt_properties[] = {
192+ DEFINE_PROP_UINT64("input-freq", RCMTState, input_freq, 0),
193+ DEFINE_PROP_END_OF_LIST(),
194+};
195+
196+static void rcmt_class_init(ObjectClass *klass, void *data)
197+{
198+ DeviceClass *dc = DEVICE_CLASS(klass);
199+
200+ dc->props = rcmt_properties;
201+ dc->vmsd = &vmstate_rcmt;
202+ dc->reset = rcmt_reset;
203+}
204+
205+static const TypeInfo rcmt_info = {
206+ .name = TYPE_RCMT,
207+ .parent = TYPE_SYS_BUS_DEVICE,
208+ .instance_size = sizeof(RCMTState),
209+ .instance_init = rcmt_init,
210+ .class_init = rcmt_class_init,
211+};
212+
213+static void rcmt_register_types(void)
214+{
215+ type_register_static(&rcmt_info);
216+}
217+
218+type_init(rcmt_register_types)
--- /dev/null
+++ b/include/hw/intc/sh7619intc.h
@@ -0,0 +1,36 @@
1+#ifndef SH7619INTC_H
2+#define SH7619INTC_H
3+
4+#include "qemu-common.h"
5+#include "hw/irq.h"
6+
7+struct IRQSource {
8+ int sense;
9+ int level;
10+ int req;
11+};
12+
13+struct SH7619INTCState {
14+ SysBusDevice parent_obj;
15+
16+ MemoryRegion memory[2];
17+ unsigned int icr0;
18+ unsigned int irqcr;
19+ unsigned int irqsr;
20+ unsigned int ipr[7];
21+ struct IRQSource src[64];
22+ qemu_irq irq;
23+ int req_irq;
24+ unsigned int read_sr;
25+};
26+typedef struct SH7619INTCState SH7619INTCState;
27+
28+#define TYPE_SH7619INTC "sh7619-intc"
29+#define SH7619INTC(obj) OBJECT_CHECK(SH7619INTCState, (obj), TYPE_SH7619INTC)
30+
31+#define TRG_LEVEL 0
32+#define TRG_NEDGE 1
33+#define TRG_PEDGE 2
34+#define TRG_BEDGE 3
35+
36+#endif /* SH7619INTC_H */
--- a/include/hw/sh4/sh.h
+++ b/include/hw/sh4/sh.h
@@ -55,4 +55,8 @@ qemu_irq sh7750_irl(struct SH7750State *s);
5555 /* tc58128.c */
5656 int tc58128_init(struct SH7750State *s, const char *zone1, const char *zone2);
5757
58+/* sh7619.c */
59+struct SH7619State;
60+struct SH7619State *sh7619_init(SuperHCPU *cpu, struct MemoryRegion *sysmem);
61+
5862 #endif
--- /dev/null
+++ b/include/hw/sh4/sh7619.h
@@ -0,0 +1,36 @@
1+/*
2+ * SH7619 Object
3+ *
4+ * Copyright (c) 2018 Yoshinori Sato
5+ *
6+ * This code is licensed under the GPL version 2 or later.
7+ *
8+ */
9+
10+#ifndef HW_RX_SH7619_H
11+#define HW_RX_SH7619_H
12+
13+#include "hw/sysbus.h"
14+#include "hw/sh4/sh.h"
15+#include "hw/intc/sh7619intc.h"
16+#include "target/sh4/cpu-qom.h"
17+
18+#define SH7619(obj) OBJECT_CHECK(SH7619State, (obj), TYPE_SH7619_CPU)
19+
20+typedef struct SH7619State {
21+ SysBusDevice parent_obj;
22+
23+ SuperHCPU *cpu;
24+ SH7619INTCState *intc;
25+
26+ MemoryRegion *sysmem;
27+ bool kernel;
28+
29+ MemoryRegion uram;
30+ MemoryRegion cache;
31+ MemoryRegion cpg;
32+ qemu_irq irq[64];
33+ uint16_t frqcr;
34+} SH7619State;
35+
36+#endif
--- a/include/hw/sh4/sh_intc.h
+++ b/include/hw/sh4/sh_intc.h
@@ -59,6 +59,7 @@ struct intc_desc {
5959 };
6060
6161 int sh_intc_get_pending_vector(struct intc_desc *desc, int imask);
62+int sh2_intc_get_pending_vector(void *state, int imask, int *level);
6263 struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id);
6364 void sh_intc_toggle_source(struct intc_source *source,
6465 int enable_adj, int assert_adj);
--- /dev/null
+++ b/include/hw/timer/renesas_cmt.h
@@ -0,0 +1,33 @@
1+/*
2+ * Renesas Compare-match timer Object
3+ *
4+ * Copyright (c) 2018 Yoshinori Sato
5+ *
6+ * This code is licensed under the GPL version 2 or later.
7+ *
8+ */
9+
10+#ifndef HW_RENESAS_CMT_H
11+#define HW_RENESAS_CMT_H
12+
13+#include "hw/sysbus.h"
14+
15+#define TYPE_RCMT "rcmt"
16+#define RCMT(obj) OBJECT_CHECK(RCMTState, (obj), TYPE_RCMT)
17+
18+typedef struct RCMTState {
19+ SysBusDevice parent_obj;
20+
21+ uint64_t input_freq;
22+ MemoryRegion memory;
23+
24+ uint16_t cmstr;
25+ uint16_t cmcr[2];
26+ uint16_t cmcnt[2];
27+ uint16_t cmcor[2];
28+ int64_t tick[2];
29+ qemu_irq cmi[2];
30+ QEMUTimer *timer[2];
31+} RCMTState;
32+
33+#endif
--- a/target/sh4/cpu-qom.h
+++ b/target/sh4/cpu-qom.h
@@ -24,6 +24,7 @@
2424
2525 #define TYPE_SUPERH_CPU "superh-cpu"
2626
27+#define TYPE_SH7619_CPU SUPERH_CPU_TYPE_NAME("sh7619")
2728 #define TYPE_SH7750R_CPU SUPERH_CPU_TYPE_NAME("sh7750r")
2829 #define TYPE_SH7751R_CPU SUPERH_CPU_TYPE_NAME("sh7751r")
2930 #define TYPE_SH7785_CPU SUPERH_CPU_TYPE_NAME("sh7785")
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -59,14 +59,23 @@ static void superh_cpu_reset(CPUState *s)
5959
6060 memset(env, 0, offsetof(CPUSH4State, end_reset_fields));
6161
62- env->pc = 0xA0000000;
62+ if (env->features != SH_FEATURE_SH2)
63+ env->pc = 0xA0000000;
64+ else {
65+ env->pc = ldl_phys(s->as, 0x00000000);
66+ env->gregs[15] = ldl_phys(s->as, 0x00000004);
67+ }
6368 #if defined(CONFIG_USER_ONLY)
6469 env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
6570 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
6671 #else
67- env->sr = (1u << SR_MD) | (1u << SR_RB) | (1u << SR_BL) |
68- (1u << SR_I3) | (1u << SR_I2) | (1u << SR_I1) | (1u << SR_I0);
69- env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
72+ if (env->features != SH_FEATURE_SH2) {
73+ env->sr = (1u << SR_MD) | (1u << SR_RB) | (1u << SR_BL) |
74+ (1u << SR_I3) | (1u << SR_I2) | (1u << SR_I1) | (1u << SR_I0);
75+ env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
76+ } else {
77+ env->sr = (1u << SR_I3) | (1u << SR_I2) | (1u << SR_I1) | (1u << SR_I0);
78+ }
7079 set_float_rounding_mode(float_round_to_zero, &env->fp_status);
7180 set_flush_to_zero(1, &env->fp_status);
7281 #endif
@@ -129,6 +138,19 @@ out:
129138 return oc;
130139 }
131140
141+static void sh7619_cpu_initfn(Object *obj)
142+{
143+ SuperHCPU *cpu = SUPERH_CPU(obj);
144+ CPUSH4State *env = &cpu->env;
145+
146+ env->id = SH_CPU_SH7619;
147+ env->features = SH_FEATURE_SH2;
148+}
149+
150+static void sh7619_class_init(ObjectClass *oc, void *data)
151+{
152+}
153+
132154 static void sh7750r_cpu_initfn(Object *obj)
133155 {
134156 SuperHCPU *cpu = SUPERH_CPU(obj);
@@ -195,8 +217,8 @@ static void superh_cpu_realizefn(DeviceState *dev, Error **errp)
195217 return;
196218 }
197219
198- cpu_reset(cs);
199220 qemu_init_vcpu(cs);
221+ cpu_reset(cs);
200222
201223 scc->parent_realize(dev, errp);
202224 }
@@ -269,6 +291,8 @@ static const TypeInfo superh_cpu_type_infos[] = {
269291 .class_size = sizeof(SuperHCPUClass),
270292 .class_init = superh_cpu_class_init,
271293 },
294+ DEFINE_SUPERH_CPU_TYPE(TYPE_SH7619_CPU, sh7619_class_init,
295+ sh7619_cpu_initfn),
272296 DEFINE_SUPERH_CPU_TYPE(TYPE_SH7750R_CPU, sh7750r_class_init,
273297 sh7750r_cpu_initfn),
274298 DEFINE_SUPERH_CPU_TYPE(TYPE_SH7751R_CPU, sh7751r_class_init,
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -33,6 +33,7 @@
3333 #define SH_CPU_SH7751 (1 << 3)
3434 #define SH_CPU_SH7751R (1 << 4)
3535 #define SH_CPU_SH7785 (1 << 5)
36+#define SH_CPU_SH7619 (1 << 6)
3637 #define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R)
3738 #define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R)
3839
@@ -138,6 +139,7 @@ typedef struct tlb_t {
138139 enum sh_features {
139140 SH_FEATURE_SH4A = 1,
140141 SH_FEATURE_BCR3_AND_BCR4 = 2,
142+ SH_FEATURE_SH2 = 3,
141143 };
142144
143145 typedef struct memory_content {
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -20,6 +20,7 @@
2020
2121 #include "cpu.h"
2222 #include "exec/exec-all.h"
23+#include "exec/cpu_ldst.h"
2324 #include "exec/log.h"
2425 #include "sysemu/sysemu.h"
2526
@@ -85,13 +86,14 @@ void superh_cpu_do_interrupt(CPUState *cs)
8586 CPUSH4State *env = &cpu->env;
8687 int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
8788 int do_exp, irq_vector = cs->exception_index;
89+ int level = 0;
8890
8991 /* prioritize exceptions over interrupts */
9092
9193 do_exp = cs->exception_index != -1;
9294 do_irq = do_irq && (cs->exception_index == -1);
9395
94- if (env->sr & (1u << SR_BL)) {
96+ if ((env->features != SH_FEATURE_SH2) && (env->sr & (1u << SR_BL))) {
9597 if (do_exp && cs->exception_index != 0x1e0) {
9698 /* In theory a masked exception generates a reset exception,
9799 which in turn jumps to the reset vector. However this only
@@ -109,8 +111,13 @@ void superh_cpu_do_interrupt(CPUState *cs)
109111 env->in_sleep = 0;
110112
111113 if (do_irq) {
112- irq_vector = sh_intc_get_pending_vector(env->intc_handle,
113- (env->sr >> 4) & 0xf);
114+ if (env->features != SH_FEATURE_SH2)
115+ irq_vector = sh_intc_get_pending_vector(env->intc_handle,
116+ (env->sr >> 4) & 0xf);
117+ else
118+ irq_vector = sh2_intc_get_pending_vector(env->intc_handle,
119+ (env->sr >> 4) & 0xf,
120+ &level);
114121 if (irq_vector == -1) {
115122 return; /* masked */
116123 }
@@ -170,8 +177,10 @@ void superh_cpu_do_interrupt(CPUState *cs)
170177 env->ssr = cpu_read_sr(env);
171178 env->spc = env->pc;
172179 env->sgr = env->gregs[15];
173- env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
174- env->lock_addr = -1;
180+ if (env->features != SH_FEATURE_SH2) {
181+ env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB);
182+ env->lock_addr = -1;
183+ }
175184
176185 if (env->flags & DELAY_SLOT_MASK) {
177186 /* Branch instruction should be executed again before delay slot. */
@@ -180,34 +189,67 @@ void superh_cpu_do_interrupt(CPUState *cs)
180189 env->flags &= ~DELAY_SLOT_MASK;
181190 }
182191
183- if (do_exp) {
184- env->expevt = cs->exception_index;
185- switch (cs->exception_index) {
186- case 0x000:
187- case 0x020:
188- case 0x140:
189- env->sr &= ~(1u << SR_FD);
190- env->sr |= 0xf << 4; /* IMASK */
191- env->pc = 0xa0000000;
192- break;
193- case 0x040:
194- case 0x060:
195- env->pc = env->vbr + 0x400;
196- break;
197- case 0x160:
198- env->spc += 2; /* special case for TRAPA */
199- /* fall through */
200- default:
201- env->pc = env->vbr + 0x100;
202- break;
192+ if (env->features == SH_FEATURE_SH2) {
193+ int v = -1;
194+ uint32_t sp = env->gregs[15];
195+ cpu_stl_kernel(env, sp, env->ssr);
196+ sp -= 4;
197+ if (!do_exp || cs->exception_index != 0x160)
198+ cpu_stl_kernel(env, sp, env->spc);
199+ else
200+ cpu_stl_kernel(env, sp, env->spc + 2);
201+ sp -= 4;
202+ env->gregs[15] = sp;
203+ env->sr &= (~0xf0);
204+ env->sr |= level << 4;
205+ if (do_exp) {
206+ switch(cs->exception_index) {
207+ case 0x180:
208+ v = 4; break;
209+ case 0x1a0:
210+ v = 6; break;
211+ case 0x0e0:
212+ case 0x100:
213+ v = 9; break;
214+ case 0x160:
215+ v = env->tra; break;
216+ }
217+ }
218+ if (do_irq) {
219+ v = irq_vector;
203220 }
221+ env->pc = cpu_ldl_kernel(env, env->vbr + v * 4);
204222 return;
205- }
223+ } else {
224+ if (do_exp) {
225+ env->expevt = cs->exception_index;
226+ switch (cs->exception_index) {
227+ case 0x000:
228+ case 0x020:
229+ case 0x140:
230+ env->sr &= ~(1u << SR_FD);
231+ env->sr |= 0xf << 4; /* IMASK */
232+ env->pc = 0xa0000000;
233+ break;
234+ case 0x040:
235+ case 0x060:
236+ env->pc = env->vbr + 0x400;
237+ break;
238+ case 0x160:
239+ env->spc += 2; /* special case for TRAPA */
240+ /* fall through */
241+ default:
242+ env->pc = env->vbr + 0x100;
243+ break;
244+ }
245+ return;
246+ }
206247
207- if (do_irq) {
208- env->intevt = irq_vector;
209- env->pc = env->vbr + 0x600;
210- return;
248+ if (do_irq) {
249+ env->intevt = irq_vector;
250+ env->pc = env->vbr + 0x600;
251+ return;
252+ }
211253 }
212254 }
213255
@@ -458,6 +500,34 @@ static int get_physical_address(CPUSH4State * env, target_ulong * physical,
458500 return get_mmu_address(env, physical, prot, address, rw, access_type);
459501 }
460502
503+static int get_physical_address_sh2(CPUSH4State * env, target_ulong * physical,
504+ int *prot, target_ulong address)
505+{
506+ /* P1, P2 and P4 areas do not use translation */
507+ if ((address >= 0x80000000 && address < 0xc0000000) ||
508+ address >= 0xe0000000) {
509+ if (address >= 0x80000000 && address < 0xc0000000) {
510+ /* Mask upper 3 bits for P1 and P2 areas */
511+ *physical = address & 0x1fffffff;
512+ } else {
513+ *physical = address;
514+ }
515+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
516+ return MMU_OK;
517+ }
518+
519+ if (address < 0x80000000) {
520+ /* P0 */
521+ *physical = address & 0x7FFFFFFF;
522+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
523+ } else {
524+ /* P3 */
525+ *physical = address & 0x1FFFFFFF;
526+ *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
527+ }
528+ return MMU_OK;
529+}
530+
461531 int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
462532 int mmu_idx)
463533 {
@@ -466,10 +536,15 @@ int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw,
466536 target_ulong physical;
467537 int prot, ret, access_type;
468538
469- access_type = ACCESS_INT;
470- ret =
471- get_physical_address(env, &physical, &prot, address, rw,
472- access_type);
539+ if (env->features != SH_FEATURE_SH2) {
540+ access_type = ACCESS_INT;
541+ ret =
542+ get_physical_address(env, &physical, &prot, address, rw,
543+ access_type);
544+ } else {
545+ ret =
546+ get_physical_address_sh2(env, &physical, &prot, address);
547+ }
473548
474549 if (ret != MMU_OK) {
475550 env->tea = address;
@@ -527,7 +602,11 @@ hwaddr superh_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
527602 target_ulong physical;
528603 int prot;
529604
530- get_physical_address(&cpu->env, &physical, &prot, addr, 0, 0);
605+ if (cpu->env.features != SH_FEATURE_SH2)
606+ get_physical_address(&cpu->env, &physical, &prot, addr, 0, 0);
607+ else
608+ get_physical_address_sh2(&cpu->env, &physical, &prot, addr);
609+
531610 return physical;
532611 }
533612
--- a/target/sh4/translate.c
+++ b/target/sh4/translate.c
@@ -373,7 +373,7 @@ static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
373373 }
374374
375375 #define CHECK_PRIVILEGED \
376- if (IS_USER(ctx)) { \
376+ if (!(ctx->features & SH_FEATURE_SH2) && IS_USER(ctx)) { \
377377 goto do_illegal; \
378378 }
379379
@@ -397,6 +397,11 @@ static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
397397 goto do_illegal; \
398398 }
399399
400+#define CHECK_SH2 \
401+ if (!(ctx->features & SH_FEATURE_SH2)) { \
402+ goto do_illegal; \
403+ }
404+
400405 static void _decode_opc(DisasContext * ctx)
401406 {
402407 /* This code tries to make movcal emulation sufficiently
@@ -451,36 +456,51 @@ static void _decode_opc(DisasContext * ctx)
451456 tcg_gen_movi_i32(cpu_macl, 0);
452457 return;
453458 case 0x0048: /* clrs */
459+ CHECK_SH2
454460 tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(1u << SR_S));
455461 return;
456462 case 0x0008: /* clrt */
457463 tcg_gen_movi_i32(cpu_sr_t, 0);
458464 return;
459465 case 0x0038: /* ldtlb */
466+ CHECK_SH2
460467 CHECK_PRIVILEGED
461468 gen_helper_ldtlb(cpu_env);
462469 return;
463470 case 0x002b: /* rte */
464471 CHECK_PRIVILEGED
465472 CHECK_NOT_DELAY_SLOT
466- gen_write_sr(cpu_ssr);
467- tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
473+ if (ctx->features != SH_FEATURE_SH2) {
474+ gen_write_sr(cpu_ssr);
475+ tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
476+ } else {
477+ TCGv sr = tcg_temp_local_new();
478+ tcg_gen_qemu_ld32u(sr, cpu_gregs[15], 0);
479+ tcg_gen_addi_i32(cpu_gregs[15], cpu_gregs[15], 4);
480+ tcg_gen_qemu_ld32u(cpu_delayed_pc, cpu_gregs[15], 0);
481+ tcg_gen_addi_i32(cpu_gregs[15], cpu_gregs[15], 4);
482+ gen_write_sr(sr);
483+ tcg_temp_free(sr);
484+ }
468485 ctx->envflags |= DELAY_SLOT_RTE;
469486 ctx->delayed_pc = (uint32_t) - 1;
470487 ctx->base.is_jmp = DISAS_STOP;
471488 return;
472489 case 0x0058: /* sets */
490+ CHECK_SH2
473491 tcg_gen_ori_i32(cpu_sr, cpu_sr, (1u << SR_S));
474492 return;
475493 case 0x0018: /* sett */
476494 tcg_gen_movi_i32(cpu_sr_t, 1);
477495 return;
478496 case 0xfbfd: /* frchg */
497+ CHECK_SH2
479498 CHECK_FPSCR_PR_0
480499 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_FR);
481500 ctx->base.is_jmp = DISAS_STOP;
482501 return;
483502 case 0xf3fd: /* fschg */
503+ CHECK_SH2
484504 CHECK_FPSCR_PR_0
485505 tcg_gen_xori_i32(cpu_fpscr, cpu_fpscr, FPSCR_SZ);
486506 ctx->base.is_jmp = DISAS_STOP;
@@ -894,6 +914,7 @@ static void _decode_opc(DisasContext * ctx)
894914 return;
895915 case 0x400c: /* shad Rm,Rn */
896916 {
917+ CHECK_SH2
897918 TCGv t0 = tcg_temp_new();
898919 TCGv t1 = tcg_temp_new();
899920 TCGv t2 = tcg_temp_new();
@@ -920,6 +941,7 @@ static void _decode_opc(DisasContext * ctx)
920941 return;
921942 case 0x400d: /* shld Rm,Rn */
922943 {
944+ CHECK_SH2
923945 TCGv t0 = tcg_temp_new();
924946 TCGv t1 = tcg_temp_new();
925947 TCGv t2 = tcg_temp_new();
@@ -989,6 +1011,7 @@ static void _decode_opc(DisasContext * ctx)
9891011 tcg_gen_xor_i32(REG(B11_8), REG(B11_8), REG(B7_4));
9901012 return;
9911013 case 0xf00c: /* fmov {F,D,X}Rm,{F,D,X}Rn - FPSCR: Nothing */
1014+ CHECK_SH2
9921015 CHECK_FPU_ENABLED
9931016 if (ctx->tbflags & FPSCR_SZ) {
9941017 int xsrc = XHACK(B7_4);
@@ -1000,6 +1023,7 @@ static void _decode_opc(DisasContext * ctx)
10001023 }
10011024 return;
10021025 case 0xf00a: /* fmov {F,D,X}Rm,@Rn - FPSCR: Nothing */
1026+ CHECK_SH2
10031027 CHECK_FPU_ENABLED
10041028 if (ctx->tbflags & FPSCR_SZ) {
10051029 TCGv_i64 fp = tcg_temp_new_i64();
@@ -1011,6 +1035,7 @@ static void _decode_opc(DisasContext * ctx)
10111035 }
10121036 return;
10131037 case 0xf008: /* fmov @Rm,{F,D,X}Rn - FPSCR: Nothing */
1038+ CHECK_SH2
10141039 CHECK_FPU_ENABLED
10151040 if (ctx->tbflags & FPSCR_SZ) {
10161041 TCGv_i64 fp = tcg_temp_new_i64();
@@ -1022,6 +1047,7 @@ static void _decode_opc(DisasContext * ctx)
10221047 }
10231048 return;
10241049 case 0xf009: /* fmov @Rm+,{F,D,X}Rn - FPSCR: Nothing */
1050+ CHECK_SH2
10251051 CHECK_FPU_ENABLED
10261052 if (ctx->tbflags & FPSCR_SZ) {
10271053 TCGv_i64 fp = tcg_temp_new_i64();
@@ -1035,6 +1061,7 @@ static void _decode_opc(DisasContext * ctx)
10351061 }
10361062 return;
10371063 case 0xf00b: /* fmov {F,D,X}Rm,@-Rn - FPSCR: Nothing */
1064+ CHECK_SH2
10381065 CHECK_FPU_ENABLED
10391066 {
10401067 TCGv addr = tcg_temp_new_i32();
@@ -1053,6 +1080,7 @@ static void _decode_opc(DisasContext * ctx)
10531080 }
10541081 return;
10551082 case 0xf006: /* fmov @(R0,Rm),{F,D,X}Rm - FPSCR: Nothing */
1083+ CHECK_SH2
10561084 CHECK_FPU_ENABLED
10571085 {
10581086 TCGv addr = tcg_temp_new_i32();
@@ -1069,6 +1097,7 @@ static void _decode_opc(DisasContext * ctx)
10691097 }
10701098 return;
10711099 case 0xf007: /* fmov {F,D,X}Rn,@(R0,Rn) - FPSCR: Nothing */
1100+ CHECK_SH2
10721101 CHECK_FPU_ENABLED
10731102 {
10741103 TCGv addr = tcg_temp_new();
@@ -1091,6 +1120,7 @@ static void _decode_opc(DisasContext * ctx)
10911120 case 0xf004: /* fcmp/eq Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
10921121 case 0xf005: /* fcmp/gt Rm,Rn - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
10931122 {
1123+ CHECK_SH2
10941124 CHECK_FPU_ENABLED
10951125 if (ctx->tbflags & FPSCR_PR) {
10961126 TCGv_i64 fp0, fp1;
@@ -1156,6 +1186,7 @@ static void _decode_opc(DisasContext * ctx)
11561186 }
11571187 return;
11581188 case 0xf00e: /* fmac FR0,RM,Rn */
1189+ CHECK_SH2
11591190 CHECK_FPU_ENABLED
11601191 CHECK_FPSCR_PR_0
11611192 gen_helper_fmac_FT(FREG(B11_8), cpu_env,
@@ -1352,19 +1383,23 @@ static void _decode_opc(DisasContext * ctx)
13521383
13531384 switch (ctx->opcode & 0xf08f) {
13541385 case 0x408e: /* ldc Rm,Rn_BANK */
1386+ CHECK_SH2
13551387 CHECK_PRIVILEGED
13561388 tcg_gen_mov_i32(ALTREG(B6_4), REG(B11_8));
13571389 return;
13581390 case 0x4087: /* ldc.l @Rm+,Rn_BANK */
1391+ CHECK_SH2
13591392 CHECK_PRIVILEGED
13601393 tcg_gen_qemu_ld_i32(ALTREG(B6_4), REG(B11_8), ctx->memidx, MO_TESL);
13611394 tcg_gen_addi_i32(REG(B11_8), REG(B11_8), 4);
13621395 return;
13631396 case 0x0082: /* stc Rm_BANK,Rn */
1397+ CHECK_SH2
13641398 CHECK_PRIVILEGED
13651399 tcg_gen_mov_i32(REG(B11_8), ALTREG(B6_4));
13661400 return;
13671401 case 0x4083: /* stc.l Rm_BANK,@-Rn */
1402+ CHECK_SH2
13681403 CHECK_PRIVILEGED
13691404 {
13701405 TCGv addr = tcg_temp_new();
@@ -1497,6 +1532,7 @@ static void _decode_opc(DisasContext * ctx)
14971532 ctx->base.is_jmp = DISAS_STOP;
14981533 return;
14991534 case 0x4066: /* lds.l @Rm+,FPSCR */
1535+ CHECK_SH2
15001536 CHECK_FPU_ENABLED
15011537 {
15021538 TCGv addr = tcg_temp_new();
@@ -1508,10 +1544,12 @@ static void _decode_opc(DisasContext * ctx)
15081544 }
15091545 return;
15101546 case 0x006a: /* sts FPSCR,Rn */
1547+ CHECK_SH2
15111548 CHECK_FPU_ENABLED
15121549 tcg_gen_andi_i32(REG(B11_8), cpu_fpscr, 0x003fffff);
15131550 return;
15141551 case 0x4062: /* sts FPSCR,@-Rn */
1552+ CHECK_SH2
15151553 CHECK_FPU_ENABLED
15161554 {
15171555 TCGv addr, val;
@@ -1615,17 +1653,20 @@ static void _decode_opc(DisasContext * ctx)
16151653 }
16161654 return;
16171655 case 0x0093: /* ocbi @Rn */
1656+ CHECK_SH2
16181657 {
16191658 gen_helper_ocbi(cpu_env, REG(B11_8));
16201659 }
16211660 return;
16221661 case 0x00a3: /* ocbp @Rn */
16231662 case 0x00b3: /* ocbwb @Rn */
1663+ CHECK_SH2
16241664 /* These instructions are supposed to do nothing in case of
16251665 a cache miss. Given that we only partially emulate caches
16261666 it is safe to simply ignore them. */
16271667 return;
16281668 case 0x0083: /* pref @Rn */
1669+ CHECK_SH2
16291670 return;
16301671 case 0x00d3: /* prefi @Rn */
16311672 CHECK_SH4A
@@ -1707,14 +1748,17 @@ static void _decode_opc(DisasContext * ctx)
17071748 }
17081749 return;
17091750 case 0xf00d: /* fsts FPUL,FRn - FPSCR: Nothing */
1751+ CHECK_SH2
17101752 CHECK_FPU_ENABLED
17111753 tcg_gen_mov_i32(FREG(B11_8), cpu_fpul);
17121754 return;
17131755 case 0xf01d: /* flds FRm,FPUL - FPSCR: Nothing */
1756+ CHECK_SH2
17141757 CHECK_FPU_ENABLED
17151758 tcg_gen_mov_i32(cpu_fpul, FREG(B11_8));
17161759 return;
17171760 case 0xf02d: /* float FPUL,FRn/DRn - FPSCR: R[PR,Enable.I]/W[Cause,Flag] */
1761+ CHECK_SH2
17181762 CHECK_FPU_ENABLED
17191763 if (ctx->tbflags & FPSCR_PR) {
17201764 TCGv_i64 fp;
@@ -1731,6 +1775,7 @@ static void _decode_opc(DisasContext * ctx)
17311775 }
17321776 return;
17331777 case 0xf03d: /* ftrc FRm/DRm,FPUL - FPSCR: R[PR,Enable.V]/W[Cause,Flag] */
1778+ CHECK_SH2
17341779 CHECK_FPU_ENABLED
17351780 if (ctx->tbflags & FPSCR_PR) {
17361781 TCGv_i64 fp;
@@ -1747,14 +1792,17 @@ static void _decode_opc(DisasContext * ctx)
17471792 }
17481793 return;
17491794 case 0xf04d: /* fneg FRn/DRn - FPSCR: Nothing */
1795+ CHECK_SH2
17501796 CHECK_FPU_ENABLED
17511797 tcg_gen_xori_i32(FREG(B11_8), FREG(B11_8), 0x80000000);
17521798 return;
17531799 case 0xf05d: /* fabs FRn/DRn - FPCSR: Nothing */
1800+ CHECK_SH2
17541801 CHECK_FPU_ENABLED
17551802 tcg_gen_andi_i32(FREG(B11_8), FREG(B11_8), 0x7fffffff);
17561803 return;
17571804 case 0xf06d: /* fsqrt FRn */
1805+ CHECK_SH2
17581806 CHECK_FPU_ENABLED
17591807 if (ctx->tbflags & FPSCR_PR) {
17601808 if (ctx->opcode & 0x0100) {
@@ -1770,21 +1818,25 @@ static void _decode_opc(DisasContext * ctx)
17701818 }
17711819 return;
17721820 case 0xf07d: /* fsrra FRn */
1821+ CHECK_SH2
17731822 CHECK_FPU_ENABLED
17741823 CHECK_FPSCR_PR_0
17751824 gen_helper_fsrra_FT(FREG(B11_8), cpu_env, FREG(B11_8));
17761825 break;
17771826 case 0xf08d: /* fldi0 FRn - FPSCR: R[PR] */
1827+ CHECK_SH2
17781828 CHECK_FPU_ENABLED
17791829 CHECK_FPSCR_PR_0
17801830 tcg_gen_movi_i32(FREG(B11_8), 0);
17811831 return;
17821832 case 0xf09d: /* fldi1 FRn - FPSCR: R[PR] */
1833+ CHECK_SH2
17831834 CHECK_FPU_ENABLED
17841835 CHECK_FPSCR_PR_0
17851836 tcg_gen_movi_i32(FREG(B11_8), 0x3f800000);
17861837 return;
17871838 case 0xf0ad: /* fcnvsd FPUL,DRn */
1839+ CHECK_SH2
17881840 CHECK_FPU_ENABLED
17891841 {
17901842 TCGv_i64 fp = tcg_temp_new_i64();
@@ -1794,6 +1846,7 @@ static void _decode_opc(DisasContext * ctx)
17941846 }
17951847 return;
17961848 case 0xf0bd: /* fcnvds DRn,FPUL */
1849+ CHECK_SH2
17971850 CHECK_FPU_ENABLED
17981851 {
17991852 TCGv_i64 fp = tcg_temp_new_i64();
@@ -1803,6 +1856,7 @@ static void _decode_opc(DisasContext * ctx)
18031856 }
18041857 return;
18051858 case 0xf0ed: /* fipr FVm,FVn */
1859+ CHECK_SH2
18061860 CHECK_FPU_ENABLED
18071861 CHECK_FPSCR_PR_1
18081862 {
@@ -1815,6 +1869,7 @@ static void _decode_opc(DisasContext * ctx)
18151869 }
18161870 break;
18171871 case 0xf0fd: /* ftrv XMTRX,FVn */
1872+ CHECK_SH2
18181873 CHECK_FPU_ENABLED
18191874 CHECK_FPSCR_PR_1
18201875 {
@@ -2256,8 +2311,11 @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
22562311 ctx->delayed_pc = -1; /* use delayed pc from env pointer */
22572312 ctx->features = env->features;
22582313 ctx->has_movcal = (tbflags & TB_FLAG_PENDING_MOVCA);
2259- ctx->gbank = ((tbflags & (1 << SR_MD)) &&
2260- (tbflags & (1 << SR_RB))) * 0x10;
2314+ if (env->features != SH_FEATURE_SH2)
2315+ ctx->gbank = ((tbflags & (1 << SR_MD)) &&
2316+ (tbflags & (1 << SR_RB))) * 0x10;
2317+ else
2318+ ctx->gbank = 0;
22612319 ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0;
22622320
22632321 if (tbflags & GUSA_MASK) {