[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 14/32] target/avr: Add instruction translation - Bit and Bit-test
From: |
Philippe Mathieu-Daudé |
Subject: |
[PULL 14/32] target/avr: Add instruction translation - Bit and Bit-test Instructions |
Date: |
Tue, 7 Jul 2020 20:16:52 +0200 |
From: Michael Rolnik <mrolnik@gmail.com>
This includes:
- LSR, ROR
- ASR
- SWAP
- SBI, CBI
- BST, BLD
- BSET, BCLR
Signed-off-by: Michael Rolnik <mrolnik@gmail.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Aleksandar Markovic <aleksandar.m.mail@gmail.com>
Signed-off-by: Thomas Huth <huth@tuxfamily.org>
Message-Id: <20200705140315.260514-15-huth@tuxfamily.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
target/avr/insn.decode | 14 +++
target/avr/translate.c | 247 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 261 insertions(+)
diff --git a/target/avr/insn.decode b/target/avr/insn.decode
index 279ddfbc0c..7bb6ce7495 100644
--- a/target/avr/insn.decode
+++ b/target/avr/insn.decode
@@ -163,3 +163,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
diff --git a/target/avr/translate.c b/target/avr/translate.c
index fce8b5af9a..884fbb6081 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -2493,3 +2493,250 @@ 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;
+}
--
2.21.3
- [PULL 05/32] target/avr: CPU class: Add migration support, (continued)
- [PULL 05/32] target/avr: CPU class: Add migration support, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 06/32] target/avr: CPU class: Add GDB support, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 07/32] target/avr: Introduce enumeration AVRFeature, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 08/32] target/avr: Add definitions of AVR core types, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 09/32] target/avr: Add instruction helpers, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 10/32] target/avr: Add instruction translation - Register definitions, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 11/32] target/avr: Add instruction translation - Arithmetic and Logic Instructions, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 12/32] target/avr: Add instruction translation - Branch Instructions, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 13/32] target/avr: Add instruction translation - Data Transfer Instructions, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 15/32] target/avr: Add instruction translation - MCU Control Instructions, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 14/32] target/avr: Add instruction translation - Bit and Bit-test Instructions,
Philippe Mathieu-Daudé <=
- [PULL 17/32] target/avr: Initialize TCG register variables, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 16/32] target/avr: Add instruction translation - CPU main translation function, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 18/32] target/avr: Add support for disassembling via option '-d in_asm', Philippe Mathieu-Daudé, 2020/07/07
- [PULL 19/32] target/avr: Register AVR support with the rest of QEMU, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 20/32] tests/machine-none: Add AVR support, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 21/32] hw/char: avr: Add limited support for USART peripheral, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 22/32] hw/timer: avr: Add limited support for 16-bit timer peripheral, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 26/32] hw/avr: Add limited support for some Arduino boards, Philippe Mathieu-Daudé, 2020/07/07
- [PULL 24/32] hw/avr: Add support for loading ELF/raw binaries, Philippe Mathieu-Daudé, 2020/07/07