From: Michael Rolnik <mrolnik@gmail.com>
To: qemu-devel@nongnu.org
Cc: thuth@redhat.com, Michael Rolnik <mrolnik@gmail.com>,
me@xcancerberox.com.ar, richard.henderson@linaro.org,
dovgaluk@ispras.ru, imammedo@redhat.com, philmd@redhat.com,
aleksandar.m.mail@gmail.com
Subject: [PATCH v40 07/21] target/avr: Add instruction translation - Bit and Bit-test Instructions
Date: Sun, 29 Dec 2019 23:51:44 +0200 [thread overview]
Message-ID: <20191229215158.5788-8-mrolnik@gmail.com> (raw)
In-Reply-To: <20191229215158.5788-1-mrolnik@gmail.com>
This includes:
- LSR, ROR
- ASR
- SWAP
- SBI, CBI
- BST, BLD
- BSET, BCLR
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
---
target/avr/translate.c | 241 +++++++++++++++++++++++++++++++++++++++++
target/avr/insn.decode | 14 +++
2 files changed, 255 insertions(+)
diff --git a/target/avr/translate.c b/target/avr/translate.c
index 9c66734a19..55706c6b29 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -2440,3 +2440,244 @@ static bool trans_LAT(DisasContext *ctx, arg_LAT *a)
return true;
}
+
+/*
+ * Bit and Bit-test Instructions
+ */
+static void gen_rshift_ZNVSf(TCGv R)
+{
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, R, 0); /* Zf = R == 0 */
+ tcg_gen_shri_tl(cpu_Nf, R, 7); /* Nf = R(7) */
+ tcg_gen_xor_tl(cpu_Vf, cpu_Nf, cpu_Cf);
+ tcg_gen_xor_tl(cpu_Sf, cpu_Nf, cpu_Vf); /* Sf = Nf ^ Vf */
+}
+
+/*
+ * Shifts all bits in Rd one place to the right. Bit 7 is cleared. Bit 0 is
+ * loaded into the C Flag of the SREG. This operation effectively divides an
+ * unsigned value by two. The C Flag can be used to round the result.
+ */
+static bool trans_LSR(DisasContext *ctx, arg_LSR *a)
+{
+ TCGv Rd = cpu_r[a->rd];
+
+ tcg_gen_andi_tl(cpu_Cf, Rd, 1);
+ tcg_gen_shri_tl(Rd, Rd, 1);
+ /* update status register */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_Zf, Rd, 0); /* Zf = Rd == 0 */
+ tcg_gen_movi_tl(cpu_Nf, 0);
+ tcg_gen_mov_tl(cpu_Vf, cpu_Cf);
+ tcg_gen_mov_tl(cpu_Sf, cpu_Vf);
+
+ return true;
+}
+
+/*
+ * Shifts all bits in Rd one place to the right. The C Flag is shifted into
+ * bit 7 of Rd. Bit 0 is shifted into the C Flag. This operation, combined
+ * with ASR, effectively divides multi-byte signed values by two. Combined with
+ * LSR it effectively divides multi-byte unsigned values by two. The Carry Flag
+ * can be used to round the result.
+ */
+static bool trans_ROR(DisasContext *ctx, arg_ROR *a)
+{
+ TCGv Rd = cpu_r[a->rd];
+ TCGv t0 = tcg_temp_new_i32();
+
+ tcg_gen_shli_tl(t0, cpu_Cf, 7);
+ /* update status register */
+ tcg_gen_andi_tl(cpu_Cf, Rd, 1);
+ /* update output register */
+ tcg_gen_shri_tl(Rd, Rd, 1);
+ tcg_gen_or_tl(Rd, Rd, t0);
+ /* update status register */
+ gen_rshift_ZNVSf(Rd);
+
+ tcg_temp_free_i32(t0);
+
+ return true;
+}
+
+/*
+ * Shifts all bits in Rd one place to the right. Bit 7 is held constant. Bit 0
+ * is loaded into the C Flag of the SREG. This operation effectively divides a
+ * signed value by two without changing its sign. The Carry Flag can be used to
+ * round the result.
+ */
+static bool trans_ASR(DisasContext *ctx, arg_ASR *a)
+{
+ TCGv Rd = cpu_r[a->rd];
+ TCGv t0 = tcg_temp_new_i32();
+
+ /* update status register */
+ tcg_gen_andi_tl(cpu_Cf, Rd, 1); /* Cf = Rd(0) */
+ /* update output register */
+ tcg_gen_andi_tl(t0, Rd, 0x80); /* Rd = (Rd & 0x80) | (Rd >> 1) */
+ tcg_gen_shri_tl(Rd, Rd, 1);
+ tcg_gen_or_tl(Rd, Rd, t0);
+ /* update status register */
+ gen_rshift_ZNVSf(Rd);
+
+ tcg_temp_free_i32(t0);
+
+ return true;
+}
+
+/*
+ * Swaps high and low nibbles in a register.
+ */
+static bool trans_SWAP(DisasContext *ctx, arg_SWAP *a)
+{
+ TCGv Rd = cpu_r[a->rd];
+ TCGv t0 = tcg_temp_new_i32();
+ TCGv t1 = tcg_temp_new_i32();
+
+ tcg_gen_andi_tl(t0, Rd, 0x0f);
+ tcg_gen_shli_tl(t0, t0, 4);
+ tcg_gen_andi_tl(t1, Rd, 0xf0);
+ tcg_gen_shri_tl(t1, t1, 4);
+ tcg_gen_or_tl(Rd, t0, t1);
+
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t0);
+
+ return true;
+}
+
+/*
+ * Sets a specified bit in an I/O Register. This instruction operates on
+ * the lower 32 I/O Registers -- addresses 0-31.
+ */
+static bool trans_SBI(DisasContext *ctx, arg_SBI *a)
+{
+ TCGv data = tcg_temp_new_i32();
+ TCGv port = tcg_const_i32(a->reg);
+
+ gen_helper_inb(data, cpu_env, port);
+ tcg_gen_ori_tl(data, data, 1 << a->bit);
+ gen_helper_outb(cpu_env, port, data);
+
+ tcg_temp_free_i32(port);
+ tcg_temp_free_i32(data);
+
+ return true;
+}
+
+/*
+ * Clears a specified bit in an I/O Register. This instruction operates on
+ * the lower 32 I/O Registers -- addresses 0-31.
+ */
+static bool trans_CBI(DisasContext *ctx, arg_CBI *a)
+{
+ TCGv data = tcg_temp_new_i32();
+ TCGv port = tcg_const_i32(a->reg);
+
+ gen_helper_inb(data, cpu_env, port);
+ tcg_gen_andi_tl(data, data, ~(1 << a->bit));
+ gen_helper_outb(cpu_env, port, data);
+
+ tcg_temp_free_i32(data);
+ tcg_temp_free_i32(port);
+
+ return true;
+}
+
+/*
+ * Stores bit b from Rd to the T Flag in SREG (Status Register).
+ */
+static bool trans_BST(DisasContext *ctx, arg_BST *a)
+{
+ TCGv Rd = cpu_r[a->rd];
+
+ tcg_gen_andi_tl(cpu_Tf, Rd, 1 << a->bit);
+ tcg_gen_shri_tl(cpu_Tf, cpu_Tf, a->bit);
+
+ return true;
+}
+
+/*
+ * Copies the T Flag in the SREG (Status Register) to bit b in register Rd.
+ */
+static bool trans_BLD(DisasContext *ctx, arg_BLD *a)
+{
+ TCGv Rd = cpu_r[a->rd];
+ TCGv t1 = tcg_temp_new_i32();
+
+ tcg_gen_andi_tl(Rd, Rd, ~(1u << a->bit)); /* clear bit */
+ tcg_gen_shli_tl(t1, cpu_Tf, a->bit); /* create mask */
+ tcg_gen_or_tl(Rd, Rd, t1);
+
+ tcg_temp_free_i32(t1);
+
+ return true;
+}
+
+/*
+ * Sets a single Flag or bit in SREG.
+ */
+static bool trans_BSET(DisasContext *ctx, arg_BSET *a)
+{
+ switch (a->bit) {
+ case 0x00:
+ tcg_gen_movi_tl(cpu_Cf, 0x01);
+ break;
+ case 0x01:
+ tcg_gen_movi_tl(cpu_Zf, 0x01);
+ break;
+ case 0x02:
+ tcg_gen_movi_tl(cpu_Nf, 0x01);
+ break;
+ case 0x03:
+ tcg_gen_movi_tl(cpu_Vf, 0x01);
+ break;
+ case 0x04:
+ tcg_gen_movi_tl(cpu_Sf, 0x01);
+ break;
+ case 0x05:
+ tcg_gen_movi_tl(cpu_Hf, 0x01);
+ break;
+ case 0x06:
+ tcg_gen_movi_tl(cpu_Tf, 0x01);
+ break;
+ case 0x07:
+ tcg_gen_movi_tl(cpu_If, 0x01);
+ break;
+ }
+
+ return true;
+}
+
+/*
+ * Clears a single Flag in SREG.
+ */
+static bool trans_BCLR(DisasContext *ctx, arg_BCLR *a)
+{
+ switch (a->bit) {
+ case 0x00:
+ tcg_gen_movi_tl(cpu_Cf, 0x00);
+ break;
+ case 0x01:
+ tcg_gen_movi_tl(cpu_Zf, 0x00);
+ break;
+ case 0x02:
+ tcg_gen_movi_tl(cpu_Nf, 0x00);
+ break;
+ case 0x03:
+ tcg_gen_movi_tl(cpu_Vf, 0x00);
+ break;
+ case 0x04:
+ tcg_gen_movi_tl(cpu_Sf, 0x00);
+ break;
+ case 0x05:
+ tcg_gen_movi_tl(cpu_Hf, 0x00);
+ break;
+ case 0x06:
+ tcg_gen_movi_tl(cpu_Tf, 0x00);
+ break;
+ case 0x07:
+ tcg_gen_movi_tl(cpu_If, 0x00);
+ break;
+ }
+
+ return true;
+}
diff --git a/target/avr/insn.decode b/target/avr/insn.decode
index 3f9304f8b0..4ee55862b2 100644
--- a/target/avr/insn.decode
+++ b/target/avr/insn.decode
@@ -158,3 +158,17 @@ XCH 1001 001 rd:5 0100
LAC 1001 001 rd:5 0110
LAS 1001 001 rd:5 0101
LAT 1001 001 rd:5 0111
+
+#
+# Bit and Bit-test Instructions
+#
+LSR 1001 010 rd:5 0110
+ROR 1001 010 rd:5 0111
+ASR 1001 010 rd:5 0101
+SWAP 1001 010 rd:5 0010
+SBI 1001 1010 reg:5 bit:3
+CBI 1001 1000 reg:5 bit:3
+BST 1111 101 rd:5 0 bit:3
+BLD 1111 100 rd:5 0 bit:3
+BSET 1001 0100 0 bit:3 1000
+BCLR 1001 0100 1 bit:3 1000
--
2.17.2 (Apple Git-113)
next prev parent reply other threads:[~2019-12-29 21:56 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-29 21:51 [PATCH v40 00/21] QEMU AVR 8 bit cores Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 01/21] target/avr: Add outward facing interfaces and core CPU logic Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 02/21] target/avr: Add instruction helpers Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 03/21] target/avr: Add instruction translation - Registers definition Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 04/21] target/avr: Add instruction translation - Arithmetic and Logic Instructions Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 05/21] target/avr: Add instruction translation - Branch Instructions Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 06/21] target/avr: Add instruction translation - Data Transfer Instructions Michael Rolnik
2019-12-29 22:31 ` Philippe Mathieu-Daudé
2019-12-29 21:51 ` Michael Rolnik [this message]
2019-12-29 22:32 ` [PATCH v40 07/21] target/avr: Add instruction translation - Bit and Bit-test Instructions Philippe Mathieu-Daudé
2019-12-29 21:51 ` [PATCH v40 08/21] target/avr: Add instruction translation - MCU Control Instructions Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 09/21] target/avr: Add instruction translation - CPU main translation function Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 10/21] target/avr: Add instruction disassembly function Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 11/21] hw/avr: Add limited support for USART peripheral Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 12/21] hw/avr: Add limited support for 16 bit timer peripheral Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 13/21] hw/avr: Add dummy mask device Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 14/21] hw/avr: Add example board configuration Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 15/21] target/avr: Add section about AVR into QEMU documentation Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 16/21] target/avr: Register AVR support with the rest of QEMU Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 17/21] target/avr: Add machine none test Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 18/21] target/avr: Update build system Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 19/21] target/avr: Add boot serial test Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 20/21] target/avr: Add Avocado test Michael Rolnik
2019-12-30 17:37 ` Wainer dos Santos Moschetta
2019-12-30 18:15 ` Michael Rolnik
2019-12-29 21:51 ` [PATCH v40 21/21] target/avr: Update MAINTAINERS file Michael Rolnik
2020-01-12 18:19 ` [PATCH v40 00/21] QEMU AVR 8 bit cores Michael Rolnik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191229215158.5788-8-mrolnik@gmail.com \
--to=mrolnik@gmail.com \
--cc=aleksandar.m.mail@gmail.com \
--cc=dovgaluk@ispras.ru \
--cc=imammedo@redhat.com \
--cc=me@xcancerberox.com.ar \
--cc=philmd@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.