/* QEMU ARM Flags test * * Copyright (c) 2008 Simon Willcocks * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* This is a test of the op_test_* routines in target-arm/op.c. * * The unpatched qemu-0.9.1 doesn't allow the N and Z flags to be * set simultaneously, although ARM processors allow it. * * The code to be emulated is: * * mov r0, #16 ; 0x10 * subs r0, r0, #1 ; 0x1 * svcvs 0x00000000 * lsl r1, r0, #28 * msr CPSR_f, r1 * mov r2, #0 ; 0x0 * orreq r2, r2, #1 ; 0x1 * orrne r2, r2, #2 ; 0x2 * orrcs r2, r2, #16 ; 0x10 * orrcc r2, r2, #32 ; 0x20 * orrmi r2, r2, #256 ; 0x100 * orrpl r2, r2, #512 ; 0x200 * orrvs r2, r2, #4096 ; 0x1000 * orrvc r2, r2, #8192 ; 0x2000 * orrhi r2, r2, #65536 ; 0x10000 * orrls r2, r2, #131072 ; 0x20000 * orrge r2, r2, #1048576 ; 0x100000 * orrlt r2, r2, #2097152 ; 0x200000 * orrgt r2, r2, #16777216 ; 0x1000000 * orrle r2, r2, #33554432 ; 0x2000000 * svc 0x00000000 * b 0xbfe115c8 * * The cpu_arm_exec routine exits for the caller to implement the svc (SWI) * instructions (when executed), and continues after them when the routine is * called again. * * The value of r2 on exit should be a leading zero and a string of 1 and 2s. */ /* Build library with: * * ./configure --disable-kqemu --disable-system --target-list=arm-linux-user \ * --disable-sdl --disable-gfx-check --disable-vnc-tls && make * * Compile this file with: * * gcc flags_test1.c -o flags_test1 qemu-0.9.1/arm-linux-user/libqemu.a \ * -I qemu-0.9.1 -DNEED_CPU_H -Iqemu-0.9.1/fpu -I qemu-0.9.1/arm-linux-user/ \ * -Wall qemu-0.9.1/osdep.c -I qemu-0.9.1/target-arm/ -D_XOPEN_SOURCE=600 * * The unpatched library outputs the following: * * bf86f878: 0000000f 01111112 NzCV * bf86f878: 0000000e 02212112 NzCv * bf86f878: 0000000d 01121122 NzcV * bf86f878: 0000000c 02222122 Nzcv * bf86f878: 0000000b 01111112 NzCV * bf86f878: 0000000a 02212112 NzCv * bf86f878: 00000009 01121122 NzcV * bf86f878: 00000008 02222122 Nzcv * bf86f878: 00000007 02221211 nZCV * bf86f878: 00000006 02122211 nZCv * bf86f878: 00000005 02221221 nZcV * bf86f878: 00000004 02122221 nZcv * bf86f878: 00000003 02211212 nzCV * bf86f878: 00000002 01112212 nzCv * bf86f878: 00000001 02221222 nzcV * bf86f878: 00000000 01122222 nzcv * * Note that the first four lines are incorrect (although the conditional * instructions are correct according to the stored flags). * * The patched library: * * bfe11618: 0000000f 02121111 NZCV * bfe11618: 0000000e 02222111 NZCv * bfe11618: 0000000d 02121121 NZcV * bfe11618: 0000000c 02222121 NZcv * bfe11618: 0000000b 01111112 NzCV * bfe11618: 0000000a 02212112 NzCv * bfe11618: 00000009 01121122 NzcV * bfe11618: 00000008 02222122 Nzcv * bfe11618: 00000007 02221211 nZCV * bfe11618: 00000006 02122211 nZCv * bfe11618: 00000005 02221221 nZcV * bfe11618: 00000004 02122221 nZcv * bfe11618: 00000003 02211212 nzCV * bfe11618: 00000002 01112212 nzCv * bfe11618: 00000001 02221222 nzcV * bfe11618: 00000000 01122222 nzcv * */ #include #include #include "cpu.h" static const char *flag_string[16] = { "nzcv", "nzcV", "nzCv", "nzCV", "nZcv", "nZcV", "nZCv", "nZCV", "Nzcv", "NzcV", "NzCv", "NzCV", "NZcv", "NZcV", "NZCv", "NZCV" }; int main() { uint32_t code[] = { 0xE3A00010, 0xE2500001, 0x6F000000, 0xE1A01E00, 0xE128F001, 0xE3A02000, 0x3822001, 0x13822002, 0x23822010, 0x33822020, 0x43822C01, 0x53822C02, 0x63822A01, 0x73822A02, 0x83822801, 0x93822802, 0xA3822601, 0xB3822602, 0xC3822401, 0xD3822402, 0xef000000, 0xEAFFFFEA }; struct CPUARMState *state = cpu_arm_init( "any" ); state->user_mode_only = 1; cpu_set_log_filename("cpu_log.txt"); cpu_set_log(0xfff); //state->singlestep_enabled = 1; state->regs[15] = (uint32_t) code; while ((cpu_arm_exec( state ) == EXCP_SWI && (state->regs[0] & 0x8000000) == 0)) { printf( "%08x: %08x %08x %s\n", state->regs[15], state->regs[0], state->regs[2], flag_string[(cpsr_read( state ) >> 28 )] ); } return 0; }