summaryrefslogtreecommitdiff
path: root/tests/tst-control.c
blob: be6f7e84023f322507ba46d0069b052e956615b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <stdio.h>
#include <string.h>
#include <libmcpu.h>
#include "../utils/mcpu-asm.h"

#define CHECK(c,m) do{if(!(c)){fprintf(stderr,"FAIL: %s\n",m);return 1;}}while(0)


static const char alias_src[]=
".text\n"
"        JZ  end\n"
"        JNZ end\n"
"        JC  end\n"
"        JNC end\n"
"        JO  end\n"
"        JNO end\n"
"        JS  end\n"
"        JNS end\n"
"end:\n"
"        HALT\n";

static const char src[]=
".text\n"
"        JMP     start\n"
"dead:\n"
"        HALT\n"
"start:\n"
"        LDI     r64@0x00000, 3\n"
"        LDI     r64@0x00008, 1\n"
"        CLR     r64@0x00010\n"
"loop:\n"
"        ISUB    r64@0x00000, r64@0x00000, r64@0x00008\n"
"        ICMP    r64@0x00000, r64@0x00010\n"
"        JNZ     loop\n"
"        JSET    ZF, done\n"
"        LDI     r64@0x00018, 77\n"
"done:\n"
"        LDI     r64@0x00018, 42\n"
"        HALT\n";

int
main( void )
{
  cpu_asm_image im, aliases;
  cpu_instruction insn;
  mpu_int64_t zero, forty_two;
  char err[256];
  int rc;

  __cpu_init();
  CHECK( cpu_assemble_text( alias_src, &aliases, err, sizeof( err ) ) == 0, err );
  CHECK( aliases.code_size == 90, "all eight jump aliases assembled" );
  cpu_asm_image_free( &aliases );

  CHECK( cpu_assemble_text( src, &im, err, sizeof( err ) ) == 0, err );
  CHECK( im.code_size > 0, "control-flow code produced" );
  CHECK( __cpu_program_set( im.code, im.code_size ) == 0, "program set" );

  __cpu_pc = 0;
  CHECK( __cpu_decode( &insn ) == 0, "decode JMP" );
  CHECK( insn.opcode == CPU_OP_JMP, "first opcode JMP" );
  CHECK( insn.length == 10, "JMP length" );
  CHECK( insn.operand[0].type == CPU_OPERAND_CODE64, "JMP CODE64 operand" );
  CHECK( insn.operand[0].value.code64 < im.code_size, "JMP target in PROGRAM" );

  rc = __cpu_run();
  CHECK( rc == CPU_EXEC_SUCCESS, "control-flow run" );
  CHECK( __cpu_pc == im.code_size, "PC after final HALT" );
  CHECK( __cpu_gth() != 0, "HALT flag set" );

  iatoi( ( mpu_int * ) zero, (__mpu_char8_t *)"0", NB_I64 );
  iatoi( ( mpu_int * ) forty_two, (__mpu_char8_t *)"42", NB_I64 );
  CHECK( !memcmp( __cpu_reg_ptr( 64, 0 ), zero, NB_I64 ), "backward JNZ loop reached zero" );
  CHECK( !memcmp( __cpu_reg_ptr( 64, 24 ), forty_two, NB_I64 ), "forward JSET reached done label" );

  cpu_asm_image_free( &im );
  __cpu_free_context();
  puts( "libcpu control-flow regression: PASS" );
  return( 0 );
}