From nobody Sat Nov 16 16:44:39 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1605111657; cv=none; d=zohomail.com; s=zohoarc; b=XehNl8dMllMS5oXzYOFVpXWCvLyEA6LHVBkJxtnqdRu9jtifS3SD1YSmFNP9CHxkrR2QCBZUKdsL9ACV2ylkcA6bDT3nTaBc3UgGcqt65qWSjrWxLt7Mi9LAPdr7DVWEV0YwneKg2CvnXG6szQwL4N9AVo1f1PyGgVxPhhQujqw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1605111657; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=vNrzXP8ZKSQ0Mw6CwtdzKT7CoLaiv0oUq3/xdqz3H1Y=; b=I+cEYsM8rLfbByJUjeGdl4kBj6YH0gd9o1HNPMi4Uxw44TkMPAQziztAJ29SzNi/KnvTp2C3DrP33jFw8irpvvzLY3ib6SJhRgJDYUnFi6ahO83P9FG8rLKAUaiaZhC8XN4uIbhmBqiFl+1ces7ri3ZKMN00vzoPeBrs29iDPao= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1605111657183434.8822322183223; Wed, 11 Nov 2020 08:20:57 -0800 (PST) Received: from localhost ([::1]:49802 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kcsrg-0003U9-8P for importer@patchew.org; Wed, 11 Nov 2020 11:20:56 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:37124) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kcsp8-0000WF-1a for qemu-devel@nongnu.org; Wed, 11 Nov 2020 11:18:18 -0500 Received: from mail-wr1-x433.google.com ([2a00:1450:4864:20::433]:37358) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kcsp3-0007wa-01 for qemu-devel@nongnu.org; Wed, 11 Nov 2020 11:18:17 -0500 Received: by mail-wr1-x433.google.com with SMTP id b6so3092245wrt.4 for ; Wed, 11 Nov 2020 08:18:12 -0800 (PST) Received: from cmiranda-laptop.localdomain (bl19-104-46.dsl.telepac.pt. [2.80.104.46]) by smtp.gmail.com with ESMTPSA id s188sm3115178wmf.45.2020.11.11.08.18.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Nov 2020 08:18:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vNrzXP8ZKSQ0Mw6CwtdzKT7CoLaiv0oUq3/xdqz3H1Y=; b=Iu5J8cSJzQ698xBhsJoNlatXLq5G6DQB++wjqGXlmrVBIOZNkmx7CElynYRovb9Rd3 wIOF4rr8YrBIZFlWp8t5OLvySHfE4a9f6mt6PaAxVqShsoQwhRvdhU1QcZx6h1JrgJ5z ifBl0/O4hm/Iob3HRf/0FPOw41U9+F74TmFetXI4oiQGixESTT4yZeuslqCIi0IFC0tc lgPaKGIw79ko7tLt5v3qtMOI0UuIL8DDV1tZWe4BnTMY2UAuqXV6FPxV9aimz2n+Ux+y oAb7hKrzPmgccat+t9StK1KLGYTYuqhJgDabYl8/QnuJmFAQ88xLIgmcdlPimTKwlJ14 DkOw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vNrzXP8ZKSQ0Mw6CwtdzKT7CoLaiv0oUq3/xdqz3H1Y=; b=eaXufoGQ/vit4Cylrjm/AJhFaU82U8hbwuGMMAOEWyC74B9NS9no7TTQhP2vg0ZKp6 /2LcByPWnokrBfB4wqM9pnosS3CmJg7piPBFY7GDaq/ModtoKqpIoekoIWkz9EK/fzwN 9EE6SbjqO80Ers2hMMVWxr9dhZMmeskPkDzBp0A5Nt9PJ9hRZAMBcGSjZsrRf9bQCsBA b9HOlK6cq9hLfLaSdv0uA9MNDJhOTLdVMc/1UVgOpzsTK9eDGR1f8Bfm8dGUEgpV5ehC atfMSRUjO0DNIvzichwK0QfmUPM4Xci0dxvIfl56X1GU/HN0z4ranGuQwrp6UYvSv48K YVog== X-Gm-Message-State: AOAM532KkMIlTdhiSV0akvtvOwwbw7oFnf/KPEDcZdqZQRVVjnlhKpng +LHgXrlBmA98TgcIDXcNrdJNHCVJN305eA== X-Google-Smtp-Source: ABdhPJzdEtDstbUHOfHiZ7x8I7ZIG9CD2nZ/1bk3rjMZNyq8E01rP7dbe9AL6GsRG4nLfJ0MTSxxLQ== X-Received: by 2002:a5d:56c7:: with SMTP id m7mr32929975wrw.201.1605111490204; Wed, 11 Nov 2020 08:18:10 -0800 (PST) From: cupertinomiranda@gmail.com To: qemu-devel@nongnu.org Subject: [PATCH 04/15] arc: TCG and decoder glue code and helpers Date: Wed, 11 Nov 2020 16:17:47 +0000 Message-Id: <20201111161758.9636-5-cupertinomiranda@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20201111161758.9636-1-cupertinomiranda@gmail.com> References: <20201111161758.9636-1-cupertinomiranda@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::433; envelope-from=cupertinomiranda@gmail.com; helo=mail-wr1-x433.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Claudiu Zissulescu , Cupertino Miranda , Shahab Vahedi , Shahab Vahedi , Cupertino Miranda , linux-snps-arc@lists.infradead.org, Claudiu Zissulescu Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" From: Cupertino Miranda Signed-off-by: Cupertino Miranda --- target/arc/extra_mapping.def | 40 ++ target/arc/helper.c | 293 +++++++++++++ target/arc/helper.h | 46 ++ target/arc/op_helper.c | 749 +++++++++++++++++++++++++++++++++ target/arc/semfunc_mapping.def | 329 +++++++++++++++ 5 files changed, 1457 insertions(+) create mode 100644 target/arc/extra_mapping.def create mode 100644 target/arc/helper.c create mode 100644 target/arc/helper.h create mode 100644 target/arc/op_helper.c create mode 100644 target/arc/semfunc_mapping.def diff --git a/target/arc/extra_mapping.def b/target/arc/extra_mapping.def new file mode 100644 index 0000000000..1387d7d483 --- /dev/null +++ b/target/arc/extra_mapping.def @@ -0,0 +1,40 @@ +/* + * QEMU ARC EXTRA MAPPING + * + * Copyright (c) 2020 Synopsys Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * http://www.gnu.org/licenses/lgpl-2.1.html + */ + +SEMANTIC_FUNCTION(SWI, 1) +SEMANTIC_FUNCTION(SWI, 1) +SEMANTIC_FUNCTION(UNIMP, 0) +SEMANTIC_FUNCTION(RTIE, 0) +SEMANTIC_FUNCTION(SLEEP, 1) + +MAPPING(swi, SWI, 0) +CONSTANT(SWI, swi_s, 0, 0) +MAPPING(swi_s, SWI, 1, 0) +MAPPING(trap_s, TRAP, 1, 0) +MAPPING(rtie, RTIE, 0) +MAPPING(sleep, SLEEP, 1, 0) +MAPPING(vadd2, VADD, 3, 0, 1, 2) +MAPPING(vadd2h, VADD, 3, 0, 1, 2) +MAPPING(vadd4h, VADD, 3, 0, 1, 2) +MAPPING(vsub2, VSUB, 3, 0, 1, 2) +MAPPING(vsub2h, VSUB, 3, 0, 1, 2) +MAPPING(vsub4h, VSUB, 3, 0, 1, 2) +MAPPING(mpyd, MPYD, 3, 0, 1, 2) +MAPPING(mpydu, MPYD, 3, 0, 1, 2) diff --git a/target/arc/helper.c b/target/arc/helper.c new file mode 100644 index 0000000000..aca7152ef8 --- /dev/null +++ b/target/arc/helper.c @@ -0,0 +1,293 @@ +/* + * QEMU ARC CPU + * + * Copyright (c) 2020 Synppsys Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * http://www.gnu.org/licenses/lgpl-2.1.html + */ + +#include "qemu/osdep.h" + +#include "cpu.h" +#include "hw/irq.h" +#include "include/hw/sysbus.h" +#include "include/sysemu/sysemu.h" +#include "qemu/qemu-print.h" +#include "exec/exec-all.h" +#include "exec/cpu_ldst.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "irq.h" + +#if defined(CONFIG_USER_ONLY) + +void arc_cpu_do_interrupt(CPUState *cs) +{ + ARCCPU *cpu =3D ARC_CPU(cs); + CPUARCState *env =3D &cpu->env; + + cs->exception_index =3D -1; + CPU_ILINK(env) =3D env->pc; +} + +#else /* !CONFIG_USER_ONLY */ + +void arc_cpu_do_interrupt(CPUState *cs) +{ + ARCCPU *cpu =3D ARC_CPU(cs); + CPUARCState *env =3D &cpu->env; + uint32_t offset =3D 0; + uint32_t vectno; + const char *name; + + /* + * NOTE: Special LP_END exception. Immediatelly return code execution = to + * lp_start. + * Now also used for delayslot MissI cases. + * This special exception should not execute any of the exception + * handling code. Instead it returns immediately after setting PC to t= he + * address passed as exception parameter. + */ + if (cs->exception_index =3D=3D EXCP_LPEND_REACHED + || cs->exception_index =3D=3D EXCP_FAKE) { + env->pc =3D env->param; + CPU_PCL(env) =3D env->pc & 0xfffffffe; + return; + } + + /* If we take an exception within an exception =3D> fatal Machine Chec= k. */ + if (env->stat.AEf =3D=3D 1) { + cs->exception_index =3D EXCP_MACHINE_CHECK; + env->causecode =3D 0; + env->param =3D 0; + env->mmu.enabled =3D false; /* no more MMU */ + env->mpu.enabled =3D false; /* no more MPU */ + } + vectno =3D cs->exception_index & 0x0F; + offset =3D vectno << 2; + + /* Generic computation for exceptions. */ + switch (cs->exception_index) { + case EXCP_RESET: + name =3D "Reset"; + break; + case EXCP_MEMORY_ERROR: + name =3D "Memory Error"; + break; + case EXCP_INST_ERROR: + name =3D "Instruction Error"; + break; + case EXCP_MACHINE_CHECK: + name =3D "Machine Check"; + break; + case EXCP_TLB_MISS_I: + name =3D "TLB Miss Instruction"; + break; + case EXCP_TLB_MISS_D: + name =3D "TLB Miss Data"; + break; + case EXCP_PROTV: + name =3D "Protection Violation"; + break; + case EXCP_PRIVILEGEV: + name =3D "Privilege Violation"; + break; + case EXCP_SWI: + name =3D "SWI"; + break; + case EXCP_TRAP: + name =3D "Trap"; + break; + case EXCP_EXTENSION: + name =3D "Extension"; + break; + case EXCP_DIVZERO: + name =3D "DIV by Zero"; + break; + case EXCP_DCERROR: + name =3D "DCError"; + break; + case EXCP_MISALIGNED: + name =3D "Misaligned"; + break; + case EXCP_IRQ: + default: + cpu_abort(cs, "unhandled exception/irq type=3D%d\n", + cs->exception_index); + break; + } + + qemu_log_mask(CPU_LOG_INT, "[EXCP] exception %d (%s) at pc=3D0x%08x\n", + cs->exception_index, name, env->pc); + + /* + * 3. exception status register is loaded with the contents + * of STATUS32. + */ + env->stat_er =3D env->stat; + + /* 4. exception return branch target address register. */ + env->erbta =3D env->bta; + + /* + * 5. eception cause register is loaded with a code to indicate + * the cause of the exception. + */ + env->ecr =3D (vectno & 0xFF) << 16; + env->ecr |=3D (env->causecode & 0xFF) << 8; + env->ecr |=3D (env->param & 0xFF); + + /* 6. Set the EFA if available. */ + if (cpu->cfg.has_mmu || cpu->cfg.has_mpu) { + switch (cs->exception_index) { + case EXCP_DCERROR: + case EXCP_DIVZERO: + case EXCP_EXTENSION: + case EXCP_TRAP: + case EXCP_SWI: + case EXCP_PRIVILEGEV: + case EXCP_MACHINE_CHECK: + case EXCP_INST_ERROR: + case EXCP_RESET: + /* TODO: this should move to the place raising the exception */ + env->efa =3D env->pc; + break; + default: + break; + } + } + + /* 7. CPU is switched to kernel mode. */ + env->stat.Uf =3D 0; + + if (env->stat_er.Uf) { + switchSP(env); + } + + /* 8. Interrupts are disabled. */ + env->stat.IEf =3D 0; + + /* 9. The active exception flag is set. */ + env->stat.AEf =3D 1; + + /* 10-14. Other flags sets. */ + env->stat.Zf =3D env->stat_er.Uf; + env->stat.Lf =3D 1; + env->stat.DEf =3D 0; + env->stat.ESf =3D 0; + env->stat.DZf =3D 0; + env->stat.SCf =3D 0; + + /* 15. The PC is set with the appropriate exception vector. */ + env->pc =3D cpu_ldl_code(env, env->intvec + offset); + CPU_PCL(env) =3D env->pc & 0xfffffffe; + + qemu_log_mask(CPU_LOG_INT, "[EXCP] isr=3D0x%x vec=3D0x%x ecr=3D0x%08x\= n", + env->pc, offset, env->ecr); + + /* Make sure that exception code decodes corectly */ + env->stat.is_delay_slot_instruction =3D 0; + + cs->exception_index =3D -1; +} + +#endif + + +static gint arc_cpu_list_compare(gconstpointer a, gconstpointer b) +{ + ObjectClass *class_a =3D (ObjectClass *)a; + ObjectClass *class_b =3D (ObjectClass *)b; + const char *name_a; + const char *name_b; + + name_a =3D object_class_get_name(class_a); + name_b =3D object_class_get_name(class_b); + if (strcmp(name_a, "any-" TYPE_ARC_CPU) =3D=3D 0) { + return 1; + } else if (strcmp(name_b, "any-" TYPE_ARC_CPU) =3D=3D 0) { + return -1; + } else { + return strcmp(name_a, name_b); + } +} + +static void arc_cpu_list_entry(gpointer data, gpointer user_data) +{ + ObjectClass *oc =3D data; + const char *typename; + char *name; + + typename =3D object_class_get_name(oc); + name =3D g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARC_CP= U)); + qemu_printf(" %s\n", name); + g_free(name); +} + +void arc_cpu_list(void) +{ + GSList *list; + + list =3D object_class_get_list(TYPE_ARC_CPU, false); + list =3D g_slist_sort(list, arc_cpu_list_compare); + qemu_printf("Available CPUs:\n"); + g_slist_foreach(list, arc_cpu_list_entry, NULL); + g_slist_free(list); +} + +int arc_cpu_memory_rw_debug(CPUState *cs, vaddr addr, uint8_t *buf, + int len, bool is_write) +{ + return cpu_memory_rw_debug(cs, addr, buf, len, is_write); +} + +hwaddr arc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) +{ + ARCCPU *cpu =3D ARC_CPU(cs); + CPUARCState *env =3D &cpu->env; + + return arc_mmu_translate(env, addr, MMU_MEM_IRRELEVANT_TYPE, + NULL); +} + +void helper_debug(CPUARCState *env) +{ + CPUState *cs =3D env_cpu(env); + + cs->exception_index =3D EXCP_DEBUG; + cpu_loop_exit(cs); +} + +/* + * raises a simple exception with causecode and parameter set to 0. + * it also considers "pc" as the exception return address. this is + * not true for a software trap. + * it is very important that "env->host_pc" holds the recent value, + * else the cpu_restore_state() will not be helpful and we end up + * with incorrect registers in env. + */ +void QEMU_NORETURN arc_raise_exception(CPUARCState *env, int32_t excp_idx) +{ + CPUState *cs =3D env_cpu(env); + cpu_restore_state(cs, env->host_pc, true); + cs->exception_index =3D excp_idx; + env->causecode =3D env->param =3D 0x0; + env->eret =3D env->pc; + env->erbta =3D env->bta; + cpu_loop_exit(cs); +} + + +/* vim: set ts=3D4 sw=3D4 et: */ diff --git a/target/arc/helper.h b/target/arc/helper.h new file mode 100644 index 0000000000..2a7e61a182 --- /dev/null +++ b/target/arc/helper.h @@ -0,0 +1,46 @@ +/* + * QEMU ARC CPU + * + * Copyright (c) 2020 Synopsys Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * href=3D"http://www.gnu.org/licenses/lgpl-2.1.html + */ + +DEF_HELPER_1(debug, void, env) +DEF_HELPER_2(norm, i32, env, i32) +DEF_HELPER_2(normh, i32, env, i32) +DEF_HELPER_2(ffs, i32, env, i32) +DEF_HELPER_2(fls, i32, env, i32) +DEF_HELPER_2(lr, tl, env, i32) +DEF_HELPER_3(sr, void, env, i32, i32) +DEF_HELPER_2(halt, noreturn, env, i32) +DEF_HELPER_1(rtie, void, env) +DEF_HELPER_1(flush, void, env) +DEF_HELPER_4(raise_exception, noreturn, env, i32, i32, i32) +DEF_HELPER_2(zol_verify, void, env, i32) +DEF_HELPER_2(fake_exception, void, env, i32) +DEF_HELPER_2(set_status32, void, env, i32) +DEF_HELPER_1(get_status32, i32, env) +DEF_HELPER_3(carry_add_flag, i32, i32, i32, i32) +DEF_HELPER_3(overflow_add_flag, i32, i32, i32, i32) +DEF_HELPER_3(overflow_sub_flag, i32, i32, i32, i32) + +DEF_HELPER_2(enter, void, env, i32) +DEF_HELPER_2(leave, void, env, i32) + +DEF_HELPER_3(mpymu, i32, env, i32, i32) +DEF_HELPER_3(mpym, i32, env, i32, i32) + +DEF_HELPER_3(repl_mask, i32, i32, i32, i32) diff --git a/target/arc/op_helper.c b/target/arc/op_helper.c new file mode 100644 index 0000000000..f24fd8c942 --- /dev/null +++ b/target/arc/op_helper.c @@ -0,0 +1,749 @@ +/* + * QEMU ARC CPU + * + * Copyright (c) 2020 Synopsys Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * http://www.gnu.org/licenses/lgpl-2.1.html + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "cpu.h" +#include "sysemu/runstate.h" +#include "exec/helper-proto.h" +#include "exec/cpu_ldst.h" +#include "exec/ioport.h" +#include "translate-all.h" +#include "target/arc/regs.h" +#include "mmu.h" +#include "hw/arc/cpudevs.h" +#include "qemu/main-loop.h" +#include "irq.h" +#include "sysemu/sysemu.h" + + +static target_ulong get_status32(CPUARCState *env) +{ + target_ulong value =3D pack_status32(&env->stat); + + /* TODO: Implement debug mode */ + if (env->stat.Uf =3D=3D 1) { + value &=3D 0x00000f00; + } + + if (env->stopped) { + value |=3D BIT(0); + } + + return value; +} + +static void set_status32(CPUARCState *env, target_ulong value) +{ + /* TODO: Implement debug mode. */ + bool debug_mode =3D false; + if (env->stat.Uf =3D=3D 1) { + value &=3D 0x00000f00; + } else if (!debug_mode) { + value &=3D 0xffff6f3f; + } + + if (((env->stat.Uf >> 7) & 0x1) !=3D ((value >> 7) & 0x1)) { + tlb_flush(env_cpu(env)); + } + + unpack_status32(&env->stat, value); + + /* Implement HALT functionality. */ + if (value & 0x01) { + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + } +} + +static void do_exception_no_delayslot(CPUARCState *env, uint32_t index, + uint32_t causecode, uint32_t param) +{ + CPUState *cs =3D env_cpu(env); + cpu_restore_state(cs, GETPC(), true); + env->eret =3D env->pc; + env->erbta =3D env->bta; + + helper_raise_exception(env, index, causecode, param); +} + +target_ulong helper_norm(CPUARCState *env, uint32_t src1) +{ + int i; + int32_t tmp =3D (int32_t) src1; + if (tmp =3D=3D 0 || tmp =3D=3D -1) { + return 0; + } + for (i =3D 0; i <=3D 31; i++) { + if ((tmp >> i) =3D=3D 0) { + break; + } + if ((tmp >> i) =3D=3D -1) { + break; + } + } + return i; +} + +target_ulong helper_normh(CPUARCState *env, uint32_t src1) +{ + int i; + for (i =3D 0; i <=3D 15; i++) { + if (src1 >> i =3D=3D 0) { + break; + } + if (src1 >> i =3D=3D -1) { + break; + } + } + return i; +} + +target_ulong helper_ffs(CPUARCState *env, uint32_t src) +{ + int i; + if (src =3D=3D 0) { + return 31; + } + for (i =3D 0; i <=3D 31; i++) { + if (((src >> i) & 1) !=3D 0) { + break; + } + } + return i; +} + +target_ulong helper_fls(CPUARCState *env, uint32_t src) +{ + int i; + if (src =3D=3D 0) { + return 0; + } + + for (i =3D 31; i >=3D 0; i--) { + if (((src >> i) & 1) !=3D 0) { + break; + } + } + return i; +} + +static void report_aux_reg_error(uint32_t aux) +{ + if (((aux >=3D ARC_BCR1_START) && (aux <=3D ARC_BCR1_END)) || + ((aux >=3D ARC_BCR2_START) && (aux <=3D ARC_BCR2_END))) { + qemu_log_mask(LOG_UNIMP, "Undefined BCR 0x%03x\n", aux); + } + + error_report("Undefined AUX register 0x%03x, aborting", aux); + exit(EXIT_FAILURE); +} + +void helper_sr(CPUARCState *env, uint32_t val, uint32_t aux) +{ + struct arc_aux_reg_detail *aux_reg_detail =3D + arc_aux_reg_struct_for_address(aux, ARC_OPCODE_ARCv2HS); + + if (aux_reg_detail =3D=3D NULL) { + report_aux_reg_error(aux); + } + + /* saving return address in case an exception must be raised later */ + env->host_pc =3D GETPC(); + + switch (aux_reg_detail->id) { + case AUX_ID_lp_start: + env->lps =3D val; + break; + + case AUX_ID_lp_end: + env->lpe =3D val; + break; + + case AUX_ID_status32: + set_status32(env, val); + break; + + case AUX_ID_eret: + env->eret =3D val; + break; + + case AUX_ID_erbta: + env->erbta =3D val; + break; + + case AUX_ID_bta: + env->bta =3D val; + break; + + case AUX_ID_erstatus: + unpack_status32(&env->stat_er, val); + break; + + case AUX_ID_ecr: + env->ecr =3D val; + break; + + case AUX_ID_efa: + env->efa =3D val; + break; + + default: + if (aux_reg_detail->aux_reg->set_func !=3D NULL) { + aux_reg_detail->aux_reg->set_func(aux_reg_detail, val, + (void *) env); + } else { + /* setting a register that does not provide one is not allowed= */ + arc_raise_exception(env, EXCP_INST_ERROR); + /* TODO: are lr and sr possible delayslot instructions ? */ + /* TODO: what is this? can it be removed? */ + do_exception_no_delayslot(env, EXCP_INST_ERROR, 0, 0); + } + break; + } + cpu_outl(aux, val); +} + +static target_ulong get_debug(CPUARCState *env) +{ + target_ulong res =3D 0x00000000; + + res |=3D (env->debug.LD) ? BIT(31) : 0; + res |=3D (env->debug.SH) ? BIT(30) : 0; + res |=3D (env->debug.BH) ? BIT(29) : 0; + res |=3D (env->debug.UB) ? BIT(28) : 0; + res |=3D (env->debug.ZZ) ? BIT(27) : 0; + res |=3D (env->debug.RA) ? BIT(22) : 0; + res |=3D (env->debug.IS) ? BIT(11) : 0; + res |=3D (env->debug.FH) ? BIT(1) : 0; + res |=3D (env->debug.SS) ? BIT(0) : 0; + + return res; +} + +static target_ulong get_identity(CPUARCState *env) +{ + target_ulong chipid =3D 0xffff, arcnum =3D 0, arcver, res; + + switch (env->family) { + case ARC_OPCODE_ARC700: + arcver =3D 0x34; + break; + + case ARC_OPCODE_ARCv2EM: + arcver =3D 0x44; + break; + + case ARC_OPCODE_ARCv2HS: + arcver =3D 0x54; + break; + + default: + arcver =3D 0; + + } + + /* TODO: in SMP, arcnum depends on the cpu instance. */ + res =3D ((chipid & 0xFFFF) << 16) | ((arcnum & 0xFF) << 8) | (arcver &= 0xFF); + return res; +} + +target_ulong helper_lr(CPUARCState *env, uint32_t aux) +{ + target_ulong result =3D 0; + + struct arc_aux_reg_detail *aux_reg_detail =3D + arc_aux_reg_struct_for_address(aux, ARC_OPCODE_ARCv2HS); + + if (aux_reg_detail =3D=3D NULL) { + report_aux_reg_error(aux); + } + + /* saving return address in case an exception must be raised later */ + env->host_pc =3D GETPC(); + + switch (aux_reg_detail->id) { + case AUX_ID_aux_volatile: + result =3D 0xc0000000; + break; + + case AUX_ID_lp_start: + result =3D env->lps; + break; + + case AUX_ID_lp_end: + result =3D env->lpe; + break; + + case AUX_ID_identity: + result =3D get_identity(env); + break; + + case AUX_ID_exec_ctrl: + result =3D 0; + break; + + case AUX_ID_debug: + result =3D get_debug(env); + break; + + case AUX_ID_pc: + result =3D env->pc & 0xfffffffe; + break; + + case AUX_ID_status32: + result =3D get_status32(env); + break; + + case AUX_ID_mpy_build: + result =3D env->mpy_build; + break; + + case AUX_ID_isa_config: + result =3D env->isa_config; + break; + + case AUX_ID_eret: + result =3D env->eret; + break; + + case AUX_ID_erbta: + result =3D env->erbta; + break; + + case AUX_ID_erstatus: + if (is_user_mode(env)) { + arc_raise_exception(env, EXCP_PRIVILEGEV); + } + result =3D pack_status32(&env->stat_er); + break; + + case AUX_ID_ecr: + result =3D env->ecr; + break; + + case AUX_ID_efa: + result =3D env->efa; + break; + + case AUX_ID_bta: + result =3D env->bta; + break; + + case AUX_ID_bta_l1: + result =3D env->bta_l1; + break; + + case AUX_ID_bta_l2: + result =3D env->bta_l2; + break; + + default: + if (aux_reg_detail->aux_reg->get_func !=3D NULL) { + result =3D aux_reg_detail->aux_reg->get_func(aux_reg_detail, + (void *) env); + } else { + /* TODO: is lr and sr possible delayslot instructions ? */ + assert(0); + arc_raise_exception(env, EXCP_INST_ERROR); + do_exception_no_delayslot(env, EXCP_INST_ERROR, 0, 0); + } + break; + } + + return result; +} + +void QEMU_NORETURN helper_halt(CPUARCState *env, uint32_t npc) +{ + CPUState *cs =3D env_cpu(env); + if (env->stat.Uf) { + cs->exception_index =3D EXCP_PRIVILEGEV; + env->causecode =3D 0; + env->param =3D 0; + /* Restore PC such that we point at the faulty instruction. */ + env->eret =3D env->pc; + } else { + env->pc =3D npc; + cs->halted =3D 1; + cs->exception_index =3D EXCP_HLT; + } + cpu_loop_exit(cs); +} + +void helper_rtie(CPUARCState *env) +{ + CPUState *cs =3D env_cpu(env); + if (env->stat.Uf) { + cs->exception_index =3D EXCP_PRIVILEGEV; + env->causecode =3D 0; + env->param =3D 0; + /* Restore PC such that we point at the faulty instruction. */ + env->eret =3D env->pc; + cpu_loop_exit(cs); + return; + } + + if (env->stat.AEf || (env->aux_irq_act & 0xFFFF) =3D=3D 0) { + assert(env->stat.Uf =3D=3D 0); + + CPU_PCL(env) =3D env->eret; + env->pc =3D env->eret; + + env->stat =3D env->stat_er; + env->bta =3D env->erbta; + + /* If returning to userland, restore SP. */ + if (env->stat.Uf) { + switchSP(env); + } + + qemu_log_mask(CPU_LOG_INT, "[EXCP] RTIE @0x%08x ECR:0x%08x\n", + env->r[63], env->ecr); + } else { + arc_rtie_interrupts(env); + qemu_log_mask(CPU_LOG_INT, "[IRQ] RTIE @0x%08x STATUS32:0x%08x\n", + env->r[63], pack_status32(&env->stat)); + } + + helper_zol_verify(env, env->pc); +} + +void helper_flush(CPUARCState *env) +{ + tb_flush((CPUState *)env_archcpu(env)); +} + +/* + * This should only be called from translate, via gen_raise_exception. + * We expect that ENV->PC has already been updated. + */ + +void QEMU_NORETURN helper_raise_exception(CPUARCState *env, + uint32_t index, + uint32_t causecode, + uint32_t param) +{ + CPUState *cs =3D env_cpu(env); + /* Cannot restore state here. */ + /* cpu_restore_state(cs, GETPC(), true); */ + cs->exception_index =3D index; + env->causecode =3D causecode; + env->param =3D param; + cpu_loop_exit(cs); +} + +void helper_zol_verify(CPUARCState *env, uint32_t npc) +{ + if (npc =3D=3D env->lpe) { + if (env->r[60] > 1) { + env->r[60] -=3D 1; + helper_raise_exception(env, (uint32_t) EXCP_LPEND_REACHED, 0, + env->lps); + } else { + env->r[60] =3D 0; + } + } +} +void helper_fake_exception(CPUARCState *env, uint32_t pc) +{ + helper_raise_exception(env, (uint32_t) EXCP_FAKE, 0, pc); +} + +uint32_t helper_get_status32(CPUARCState *env) +{ + return get_status32(env); +} + +void helper_set_status32(CPUARCState *env, uint32_t value) +{ + set_status32(env, value); +} + +uint32_t helper_carry_add_flag(uint32_t dest, uint32_t b, uint32_t c) +{ + uint32_t t1, t2, t3; + + t1 =3D b & c; + t2 =3D b & (~dest); + t3 =3D c & (~dest); + t1 =3D t1 | t2 | t3; + return (t1 >> 31) & 1; +} + +uint32_t helper_overflow_add_flag(uint32_t dest, uint32_t b, uint32_t c) +{ + dest >>=3D 31; + b >>=3D 31; + c >>=3D 31; + if ((dest =3D=3D 0 && b =3D=3D 1 && c =3D=3D 1) + || (dest =3D=3D 1 && b =3D=3D 0 && c =3D=3D 0)) { + return 1; + } else { + return 0; + } +} + +uint32_t helper_overflow_sub_flag(uint32_t dest, uint32_t b, uint32_t c) +{ + dest >>=3D 31; + b >>=3D 31; + c >>=3D 31; + if ((dest =3D=3D 1 && b =3D=3D 0 && c =3D=3D 1) + || (dest =3D=3D 0 && b =3D=3D 1 && c =3D=3D 0)) { + return 1; + } else { + return 0; + } +} + +uint32_t helper_repl_mask(uint32_t dest, uint32_t src, uint32_t mask) +{ + uint32_t ret =3D dest & (~mask); + ret |=3D (src & mask); + + return ret; +} + +uint32_t helper_mpymu(CPUARCState *env, uint32_t b, uint32_t c) +{ + uint64_t _b =3D (uint64_t) b; + uint64_t _c =3D (uint64_t) c; + + return (uint32_t) ((_b * _c) >> 32); +} + +uint32_t helper_mpym(CPUARCState *env, uint32_t b, uint32_t c) +{ + int64_t _b =3D (int64_t) ((int32_t) b); + int64_t _c =3D (int64_t) ((int32_t) c); + + /* + * fprintf(stderr, "B =3D 0x%llx, C =3D 0x%llx, result =3D 0x%llx\n", + * _b, _c, _b * _c); + */ + return (_b * _c) >> 32; +} + + +/* + * throw "illegal instruction" exception if more than available + * registers are asked to be saved/restore. + */ +static void check_enter_leave_nr_regs(CPUARCState *env, + uint8_t regs, + uintptr_t host_pc) +{ + const uint8_t rgf_num_regs =3D env_archcpu(env)->cfg.rgf_num_regs; + if ((rgf_num_regs =3D=3D 32 && regs > 14) || + (rgf_num_regs =3D=3D 16 && regs > 3)) { + CPUState *cs =3D env_cpu(env); + cpu_restore_state(cs, host_pc, true); + cs->exception_index =3D EXCP_INST_ERROR; + env->causecode =3D 0x00; + env->param =3D 0x00; + env->eret =3D env->pc; + env->erbta =3D env->bta; + cpu_loop_exit(cs); + } +} + +/* + * throw "illegal instruction sequence" exception if we are in a + * delay/execution slot. + */ +static void check_delay_or_execution_slot(CPUARCState *env, + uintptr_t host_pc) +{ + if (env->stat.DEf || env->stat.ESf) { + CPUState *cs =3D env_cpu(env); + cpu_restore_state(cs, host_pc, true); + cs->exception_index =3D EXCP_INST_ERROR; + env->causecode =3D 0x01; + env->param =3D 0x00; + env->eret =3D env->pc; + env->erbta =3D env->bta; + cpu_loop_exit(cs); + } +} + +/* + * Throw "misaligned" exception if 'addr' is not 32-bit aligned. + * This check is done irrelevant of status32.AD bit. + */ +static void check_addr_is_word_aligned(CPUARCState *env, + target_ulong addr, + uintptr_t host_pc) +{ + if (addr & 0x3) { + CPUState *cs =3D env_cpu(env); + cpu_restore_state(cs, host_pc, true); + cs->exception_index =3D EXCP_MISALIGNED; + env->causecode =3D 0x00; + env->param =3D 0x00; + env->efa =3D addr; + env->eret =3D env->pc; + env->erbta =3D env->bta; + cpu_loop_exit(cs); + } +} + +/* + * helper for enter_s instruction. + * after we are done, stack layout would be: + * ,- top -. + * | blink | + * | r13 | + * | r14 | + * | ... | + * | r26 | + * | fp | + * `-------' + */ +void helper_enter(CPUARCState *env, uint32_t u6) +{ + /* nothing to do? then bye-bye! */ + if (!u6) { + return; + } + + uint8_t regs =3D u6 & 0x0f; /* u[3:0] determines registers to sa= ve */ + bool save_fp =3D u6 & 0x10; /* u[4] indicates if fp must be save= d */ + bool save_blink =3D u6 & 0x20; /* u[5] indicates saving of blink = */ + uint8_t stack_size =3D 4 * (regs + save_fp + save_blink); + + /* number of regs to be saved must be sane */ + check_enter_leave_nr_regs(env, regs, GETPC()); + + /* this cannot be executed in a delay/execution slot */ + check_delay_or_execution_slot(env, GETPC()); + + /* stack must be a multiple of 4 (32 bit aligned) */ + check_addr_is_word_aligned(env, CPU_SP(env) - stack_size, GETPC()); + + uint32_t tmp_sp =3D CPU_SP(env); + + if (save_fp) { + tmp_sp -=3D 4; + cpu_stl_data(env, tmp_sp, CPU_FP(env)); + } + + for (uint8_t gpr =3D regs; gpr >=3D 1; --gpr) { + tmp_sp -=3D 4; + cpu_stl_data(env, tmp_sp, env->r[13 + gpr - 1]); + } + + if (save_blink) { + tmp_sp -=3D 4; + cpu_stl_data(env, tmp_sp, CPU_BLINK(env)); + } + + CPU_SP(env) =3D tmp_sp; + + /* now that sp has been allocated, shall we write it to fp? */ + if (save_fp) { + CPU_FP(env) =3D CPU_SP(env); + } +} + +/* + * helper for leave_s instruction. + * a stack layout of below is assumed: + * ,- top -. + * | blink | + * | r13 | + * | r14 | + * | ... | + * | r26 | + * | fp | + * `-------' + */ +void helper_leave(CPUARCState *env, uint32_t u7) +{ + /* nothing to do? then bye-bye! */ + if (!u7) { + return; + } + + uint8_t regs =3D u7 & 0x0f; /* u[3:0] determines registers to sa= ve */ + bool restore_fp =3D u7 & 0x10; /* u[4] indicates if fp must be save= d */ + bool restore_blink =3D u7 & 0x20; /* u[5] indicates saving of blink = */ + bool jump_to_blink =3D u7 & 0x40; /* u[6] should we jump to blink? = */ + + /* number of regs to be restored must be sane */ + check_enter_leave_nr_regs(env, regs, GETPC()); + + /* this cannot be executed in a delay/execution slot */ + check_delay_or_execution_slot(env, GETPC()); + + /* + * stack must be a multiple of 4 (32 bit aligned). we must take into + * account if sp is going to use fp's value or not. + */ + const target_ulong addr =3D restore_fp ? CPU_FP(env) : CPU_SP(env); + check_addr_is_word_aligned(env, addr, GETPC()); + + /* + * if fp is in the picture, then first we have to use the current + * fp as the stack pointer for restoring. + */ + if (restore_fp) { + CPU_SP(env) =3D CPU_FP(env); + } + + uint32_t tmp_sp =3D CPU_SP(env); + + if (restore_blink) { + CPU_BLINK(env) =3D cpu_ldl_data(env, tmp_sp); + tmp_sp +=3D 4; + } + + for (uint8_t gpr =3D 0; gpr < regs; ++gpr) { + env->r[13 + gpr] =3D cpu_ldl_data(env, tmp_sp); + tmp_sp +=3D 4; + } + + if (restore_fp) { + CPU_FP(env) =3D cpu_ldl_data(env, tmp_sp); + tmp_sp +=3D 4; + } + + CPU_SP(env) =3D tmp_sp; + + /* now that we are done, should we jump to blink? */ + if (jump_to_blink) { + CPU_PCL(env) =3D CPU_BLINK(env); + env->pc =3D CPU_BLINK(env); + } +} + +/* + * uint32_t lf_variable =3D 0; + * uint32_t helper_get_lf(void) + * { + * return lf_variable; + * } + * void helper_set_lf(uint32_t v) + * { + * lf_variable =3D v; + * } + */ + +/*-*-indent-tabs-mode:nil;tab-width:4;indent-line-function:'insert-tab'-*-= */ +/* vim: set ts=3D4 sw=3D4 et: */ diff --git a/target/arc/semfunc_mapping.def b/target/arc/semfunc_mapping.def new file mode 100644 index 0000000000..b47edb42e5 --- /dev/null +++ b/target/arc/semfunc_mapping.def @@ -0,0 +1,329 @@ +/* + * QEMU ARC SEMANTIC MAPPING. + * + * Copyright (c) 2020 Synopsys, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License f= or + * more details. + * + * You should have received a copy of the GNU General Public License along= with + * this program. If not, see . + */ + +SEMANTIC_FUNCTION(FLAG, 1) +SEMANTIC_FUNCTION(KFLAG, 1) +SEMANTIC_FUNCTION(ADD, 3) +SEMANTIC_FUNCTION(ADD1, 3) +SEMANTIC_FUNCTION(ADD2, 3) +SEMANTIC_FUNCTION(ADD3, 3) +SEMANTIC_FUNCTION(ADC, 3) +SEMANTIC_FUNCTION(SBC, 3) +SEMANTIC_FUNCTION(NEG, 2) +SEMANTIC_FUNCTION(SUB, 3) +SEMANTIC_FUNCTION(SUB1, 3) +SEMANTIC_FUNCTION(SUB2, 3) +SEMANTIC_FUNCTION(SUB3, 3) +SEMANTIC_FUNCTION(MAX, 3) +SEMANTIC_FUNCTION(MIN, 3) +SEMANTIC_FUNCTION(CMP, 2) +SEMANTIC_FUNCTION(AND, 3) +SEMANTIC_FUNCTION(OR, 3) +SEMANTIC_FUNCTION(XOR, 3) +SEMANTIC_FUNCTION(MOV, 2) +SEMANTIC_FUNCTION(ASL, 3) +SEMANTIC_FUNCTION(ASR, 3) +SEMANTIC_FUNCTION(ASR8, 2) +SEMANTIC_FUNCTION(ASR16, 2) +SEMANTIC_FUNCTION(LSL16, 2) +SEMANTIC_FUNCTION(LSL8, 2) +SEMANTIC_FUNCTION(LSR, 3) +SEMANTIC_FUNCTION(LSR16, 2) +SEMANTIC_FUNCTION(LSR8, 2) +SEMANTIC_FUNCTION(BIC, 3) +SEMANTIC_FUNCTION(BCLR, 3) +SEMANTIC_FUNCTION(BMSK, 3) +SEMANTIC_FUNCTION(BMSKN, 3) +SEMANTIC_FUNCTION(BSET, 3) +SEMANTIC_FUNCTION(BXOR, 3) +SEMANTIC_FUNCTION(ROL, 2) +SEMANTIC_FUNCTION(ROL8, 2) +SEMANTIC_FUNCTION(ROR, 3) +SEMANTIC_FUNCTION(ROR8, 2) +SEMANTIC_FUNCTION(RLC, 2) +SEMANTIC_FUNCTION(RRC, 2) +SEMANTIC_FUNCTION(SEXB, 2) +SEMANTIC_FUNCTION(SEXH, 2) +SEMANTIC_FUNCTION(EXTB, 2) +SEMANTIC_FUNCTION(EXTH, 2) +SEMANTIC_FUNCTION(BTST, 2) +SEMANTIC_FUNCTION(TST, 2) +SEMANTIC_FUNCTION(XBFU, 3) +SEMANTIC_FUNCTION(AEX, 2) +SEMANTIC_FUNCTION(LR, 2) +SEMANTIC_FUNCTION(SR, 2) +SEMANTIC_FUNCTION(SYNC, 0) +SEMANTIC_FUNCTION(CLRI, 1) +SEMANTIC_FUNCTION(SETI, 1) +SEMANTIC_FUNCTION(NOP, 0) +SEMANTIC_FUNCTION(PREALLOC, 0) +SEMANTIC_FUNCTION(PREFETCH, 2) +SEMANTIC_FUNCTION(MPY, 3) +SEMANTIC_FUNCTION(MPYMU, 3) +SEMANTIC_FUNCTION(MPYM, 3) +SEMANTIC_FUNCTION(MPYU, 3) +SEMANTIC_FUNCTION(MPYUW, 3) +SEMANTIC_FUNCTION(MPYW, 3) +SEMANTIC_FUNCTION(DIV, 3) +SEMANTIC_FUNCTION(DIVU, 3) +SEMANTIC_FUNCTION(REM, 3) +SEMANTIC_FUNCTION(REMU, 3) +SEMANTIC_FUNCTION(MAC, 3) +SEMANTIC_FUNCTION(MACU, 3) +SEMANTIC_FUNCTION(MACD, 3) +SEMANTIC_FUNCTION(MACDU, 3) +SEMANTIC_FUNCTION(ABS, 2) +SEMANTIC_FUNCTION(SWAP, 2) +SEMANTIC_FUNCTION(SWAPE, 2) +SEMANTIC_FUNCTION(NOT, 2) +SEMANTIC_FUNCTION(BI, 1) +SEMANTIC_FUNCTION(BIH, 1) +SEMANTIC_FUNCTION(B, 1) +SEMANTIC_FUNCTION(B_S, 1) +SEMANTIC_FUNCTION(BBIT0, 3) +SEMANTIC_FUNCTION(BBIT1, 3) +SEMANTIC_FUNCTION(BL, 1) +SEMANTIC_FUNCTION(J, 1) +SEMANTIC_FUNCTION(JL, 1) +SEMANTIC_FUNCTION(SETEQ, 3) +SEMANTIC_FUNCTION(BREQ, 3) +SEMANTIC_FUNCTION(SETNE, 3) +SEMANTIC_FUNCTION(BRNE, 3) +SEMANTIC_FUNCTION(SETLT, 3) +SEMANTIC_FUNCTION(BRLT, 3) +SEMANTIC_FUNCTION(SETGE, 3) +SEMANTIC_FUNCTION(BRGE, 3) +SEMANTIC_FUNCTION(SETLE, 3) +SEMANTIC_FUNCTION(SETGT, 3) +SEMANTIC_FUNCTION(BRLO, 3) +SEMANTIC_FUNCTION(SETLO, 3) +SEMANTIC_FUNCTION(BRHS, 3) +SEMANTIC_FUNCTION(SETHS, 3) +SEMANTIC_FUNCTION(EX, 2) +SEMANTIC_FUNCTION(LLOCK, 2) +SEMANTIC_FUNCTION(LLOCKD, 2) +SEMANTIC_FUNCTION(SCOND, 2) +SEMANTIC_FUNCTION(SCONDD, 2) +SEMANTIC_FUNCTION(DMB, 1) +SEMANTIC_FUNCTION(LD, 3) +SEMANTIC_FUNCTION(LDD, 3) +SEMANTIC_FUNCTION(ST, 3) +SEMANTIC_FUNCTION(STD, 3) +SEMANTIC_FUNCTION(ENTER_S, 1) +SEMANTIC_FUNCTION(LEAVE_S, 1) +SEMANTIC_FUNCTION(POP, 1) +SEMANTIC_FUNCTION(PUSH, 1) +SEMANTIC_FUNCTION(LP, 1) +SEMANTIC_FUNCTION(NORM, 2) +SEMANTIC_FUNCTION(NORMH, 2) +SEMANTIC_FUNCTION(FLS, 2) +SEMANTIC_FUNCTION(FFS, 2) + + +MAPPING(flag, FLAG, 1, 0) +MAPPING(kflag, KFLAG, 1, 0) +MAPPING(add, ADD, 3, 1, 2, 0) +MAPPING(add_s, ADD, 3, 1, 2, 0) +MAPPING(add1, ADD1, 3, 1, 2, 0) +MAPPING(add1_s, ADD1, 3, 1, 2, 0) +MAPPING(add2, ADD2, 3, 1, 2, 0) +MAPPING(add2_s, ADD2, 3, 1, 2, 0) +MAPPING(add3, ADD3, 3, 1, 2, 0) +MAPPING(add3_s, ADD3, 3, 1, 2, 0) +MAPPING(adc, ADC, 3, 1, 2, 0) +MAPPING(sbc, SBC, 3, 1, 2, 0) +MAPPING(neg, NEG, 2, 1, 0) +MAPPING(neg_s, NEG, 2, 1, 0) +MAPPING(sub, SUB, 3, 1, 2, 0) +MAPPING(sub_s, SUB, 3, 1, 2, 0) +MAPPING(rsub, SUB, 3, 2, 1, 0) +MAPPING(sub1, SUB1, 3, 1, 2, 0) +MAPPING(sub2, SUB2, 3, 1, 2, 0) +MAPPING(sub3, SUB3, 3, 1, 2, 0) +MAPPING(max, MAX, 3, 1, 2, 0) +MAPPING(min, MIN, 3, 1, 2, 0) +MAPPING(cmp, CMP, 2, 0, 1) +MAPPING(cmp_s, CMP, 2, 0, 1) +MAPPING(rcmp, CMP, 2, 1, 0) +MAPPING(and, AND, 3, 1, 2, 0) +MAPPING(and_s, AND, 3, 1, 2, 0) +MAPPING(or, OR, 3, 1, 2, 0) +MAPPING(or_s, OR, 3, 1, 2, 0) +MAPPING(xor, XOR, 3, 1, 2, 0) +MAPPING(xor_s, XOR, 3, 1, 2, 0) +MAPPING(mov, MOV, 2, 1, 0) +MAPPING(mov_s, MOV, 2, 1, 0) +CONSTANT(ASL, asl, 2, 268435457) /* For variable @c */ +MAPPING(asl, ASL, 3, 1, 2, 0) +CONSTANT(ASL, asl_s, 2, 268435457) /* For variable @c */ +MAPPING(asl_s, ASL, 3, 1, 2, 0) +CONSTANT(ASR, asr, 2, 1) /* For variable @c */ +MAPPING(asr, ASR, 3, 1, 2, 0) +CONSTANT(ASR, asr_s, 2, 1) /* For variable @c */ +MAPPING(asr_s, ASR, 3, 1, 2, 0) +MAPPING(asr8, ASR8, 2, 1, 0) +MAPPING(asr16, ASR16, 2, 1, 0) +MAPPING(lsl16, LSL16, 2, 1, 0) +MAPPING(lsl8, LSL8, 2, 1, 0) +CONSTANT(LSR, lsr, 2, 1) /* For variable @c */ +MAPPING(lsr, LSR, 3, 1, 2, 0) +CONSTANT(LSR, lsr_s, 2, 1) /* For variable @c */ +MAPPING(lsr_s, LSR, 3, 1, 2, 0) +MAPPING(lsr16, LSR16, 2, 1, 0) +MAPPING(lsr8, LSR8, 2, 1, 0) +MAPPING(bic, BIC, 3, 1, 2, 0) +MAPPING(bic_s, BIC, 3, 1, 2, 0) +MAPPING(bclr, BCLR, 3, 2, 1, 0) +MAPPING(bclr_s, BCLR, 3, 2, 1, 0) +MAPPING(bmsk, BMSK, 3, 2, 1, 0) +MAPPING(bmsk_s, BMSK, 3, 2, 1, 0) +MAPPING(bmskn, BMSKN, 3, 2, 1, 0) +MAPPING(bset, BSET, 3, 2, 1, 0) +MAPPING(bset_s, BSET, 3, 2, 1, 0) +MAPPING(bxor, BXOR, 3, 2, 1, 0) +MAPPING(rol, ROL, 2, 1, 0) +MAPPING(rol8, ROL8, 2, 1, 0) +CONSTANT(ROR, ror, 2, 1) /* For variable @n */ +MAPPING(ror, ROR, 3, 1, 2, 0) +MAPPING(ror8, ROR8, 2, 1, 0) +MAPPING(rlc, RLC, 2, 1, 0) +MAPPING(rrc, RRC, 2, 1, 0) +MAPPING(sexb, SEXB, 2, 0, 1) +MAPPING(sexb_s, SEXB, 2, 0, 1) +MAPPING(sexh, SEXH, 2, 0, 1) +MAPPING(sexh_s, SEXH, 2, 0, 1) +MAPPING(extb, EXTB, 2, 0, 1) +MAPPING(extb_s, EXTB, 2, 0, 1) +MAPPING(exth, EXTH, 2, 0, 1) +MAPPING(exth_s, EXTH, 2, 0, 1) +MAPPING(btst, BTST, 2, 1, 0) +MAPPING(btst_s, BTST, 2, 1, 0) +MAPPING(tst, TST, 2, 0, 1) +MAPPING(tst_s, TST, 2, 0, 1) +MAPPING(xbfu, XBFU, 3, 2, 1, 0) +MAPPING(aex, AEX, 2, 1, 0) +MAPPING(lr, LR, 2, 0, 1) +MAPPING(sr, SR, 2, 1, 0) +MAPPING(sync, SYNC, 0) +MAPPING(clri, CLRI, 1, 0) +MAPPING(seti, SETI, 1, 0) +MAPPING(nop, NOP, 0) +MAPPING(nop_s, NOP, 0) +MAPPING(prealloc, PREALLOC, 0) +CONSTANT(PREFETCH, prefetch, 1, 0) /* For variable @src2 */ +MAPPING(prefetch, PREFETCH, 2, 0, 1) +CONSTANT(PREFETCH, prefetchw, 1, 0) /* For variable @src2 */ +MAPPING(prefetchw, PREFETCH, 2, 0, 1) +MAPPING(mpy, MPY, 3, 1, 2, 0) +MAPPING(mpy_s, MPY, 3, 1, 2, 0) +MAPPING(mpymu, MPYMU, 3, 0, 1, 2) +MAPPING(mpym, MPYM, 3, 0, 1, 2) +MAPPING(mpyu, MPYU, 3, 1, 2, 0) +MAPPING(mpyuw, MPYUW, 3, 0, 1, 2) +MAPPING(mpyuw_s, MPYUW, 3, 0, 1, 2) +MAPPING(mpyw, MPYW, 3, 0, 1, 2) +MAPPING(mpyw_s, MPYW, 3, 0, 1, 2) +MAPPING(div, DIV, 3, 2, 1, 0) +MAPPING(divu, DIVU, 3, 2, 0, 1) +MAPPING(rem, REM, 3, 2, 1, 0) +MAPPING(remu, REMU, 3, 2, 0, 1) +MAPPING(mac, MAC, 3, 1, 2, 0) +MAPPING(macu, MACU, 3, 1, 2, 0) +MAPPING(macd, MACD, 3, 1, 2, 0) +MAPPING(macdu, MACDU, 3, 1, 2, 0) +MAPPING(abs, ABS, 2, 1, 0) +MAPPING(abs_s, ABS, 2, 1, 0) +MAPPING(swap, SWAP, 2, 1, 0) +MAPPING(swape, SWAPE, 2, 1, 0) +MAPPING(not, NOT, 2, 0, 1) +MAPPING(not_s, NOT, 2, 0, 1) +MAPPING(bi, BI, 1, 0) +MAPPING(bih, BIH, 1, 0) +MAPPING(b, B, 1, 0) +MAPPING(beq_s, B_S, 1, 0) +MAPPING(bne_s, B_S, 1, 0) +MAPPING(bgt_s, B_S, 1, 0) +MAPPING(bge_s, B_S, 1, 0) +MAPPING(blt_s, B_S, 1, 0) +MAPPING(ble_s, B_S, 1, 0) +MAPPING(bhi_s, B_S, 1, 0) +MAPPING(bhs_s, B_S, 1, 0) +MAPPING(blo_s, B_S, 1, 0) +MAPPING(bls_s, B_S, 1, 0) +MAPPING(b_s, B_S, 1, 0) +MAPPING(bbit0, BBIT0, 3, 0, 1, 2) +MAPPING(bbit1, BBIT1, 3, 0, 1, 2) +MAPPING(bl, BL, 1, 0) +MAPPING(bl_s, BL, 1, 0) +MAPPING(j, J, 1, 0) +MAPPING(j_s, J, 1, 0) +MAPPING(jeq_s, J, 1, 0) +MAPPING(jne_s, J, 1, 0) +MAPPING(jl, JL, 1, 0) +MAPPING(jl_s, JL, 1, 0) +MAPPING(seteq, SETEQ, 3, 1, 2, 0) +MAPPING(breq, BREQ, 3, 0, 1, 2) +MAPPING(breq_s, BREQ, 3, 0, 1, 2) +MAPPING(setne, SETNE, 3, 1, 2, 0) +MAPPING(brne, BRNE, 3, 0, 1, 2) +MAPPING(brne_s, BRNE, 3, 0, 1, 2) +MAPPING(setlt, SETLT, 3, 1, 2, 0) +MAPPING(brlt, BRLT, 3, 0, 1, 2) +MAPPING(setge, SETGE, 3, 1, 2, 0) +MAPPING(brge, BRGE, 3, 0, 1, 2) +MAPPING(setle, SETLE, 3, 1, 2, 0) +MAPPING(setgt, SETGT, 3, 1, 2, 0) +MAPPING(brlo, BRLO, 3, 0, 1, 2) +MAPPING(setlo, SETLO, 3, 1, 2, 0) +MAPPING(brhs, BRHS, 3, 0, 1, 2) +MAPPING(seths, SETHS, 3, 1, 2, 0) +MAPPING(ex, EX, 2, 0, 1) +MAPPING(llock, LLOCK, 2, 0, 1) +MAPPING(llockd, LLOCKD, 2, 0, 1) +MAPPING(scond, SCOND, 2, 1, 0) +MAPPING(scondd, SCONDD, 2, 1, 0) +MAPPING(dmb, DMB, 1, 0) +CONSTANT(LD, ld, 2, 0) /* For variable @src2 */ +MAPPING(ld, LD, 3, 1, 2, 0) +MAPPING(ld_s, LD, 3, 1, 2, 0) +MAPPING(ldb_s, LD, 3, 1, 2, 0) +MAPPING(ldh_s, LD, 3, 1, 2, 0) +MAPPING(ldw_s, LD, 3, 1, 2, 0) +CONSTANT(LD, ldi, 2, 0) /* For variable @src2 */ +MAPPING(ldi, LD, 3, 1, 2, 0) +CONSTANT(LD, ldi_s, 2, 0) /* For variable @src2 */ +MAPPING(ldi_s, LD, 3, 1, 2, 0) +CONSTANT(LDD, ldd, 2, 0) /* For variable @src2 */ +MAPPING(ldd, LDD, 3, 1, 2, 0) +CONSTANT(ST, st, 2, 0) /* For variable @src2 */ +MAPPING(st, ST, 3, 1, 2, 0) +MAPPING(st_s, ST, 3, 1, 2, 0) +MAPPING(stb_s, ST, 3, 1, 2, 0) +MAPPING(sth_s, ST, 3, 1, 2, 0) +MAPPING(stw_s, ST, 3, 1, 2, 0) +CONSTANT(STD, std, 2, 0) /* For variable @src2 */ +MAPPING(std, STD, 3, 1, 2, 0) +MAPPING(enter_s, ENTER_S, 1, 0) +MAPPING(leave_s, LEAVE_S, 1, 0) +MAPPING(pop_s, POP, 1, 0) +MAPPING(push_s, PUSH, 1, 0) +MAPPING(lp, LP, 1, 0) +MAPPING(norm, NORM, 2, 1, 0) +MAPPING(normh, NORMH, 2, 1, 0) +MAPPING(fls, FLS, 2, 1, 0) +MAPPING(ffs, FFS, 2, 1, 0) --=20 2.20.1