summaryrefslogtreecommitdiffstats
path: root/src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.c
blob: 11d7a9618fbe82a537094753280a583a309cadeb (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.c $    */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2012,2013              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// $Id: pore_inline_decode.c,v 1.4 2013/11/27 15:52:00 thi Exp $
#include <stdint.h>
#include "pore_inline_decode.h"

// From a uint32_t, extract a big-endian bit x[i] as either 0 or 1

#define BE_BIT_32(x, i) (((x) >> (31 - (i))) & 1)


// From a uint32_t, extract big-endian bits x[first:last] as unsigned to
// create a uint32_t.

#define BE_BITS_32_UNSIGNED(x, first, last) \
    (((x) >> (31 - (last))) & (0xffffffff >> (32 - (last - first + 1))))


// From a uint32_t, extract big-endian bits x[first:last] as signed to create
// an int32_t.

#define BE_BITS_32_SIGNED(x, first, last) \
    (((x) & (1 << (31 - (first)))) ? \
     (BE_BITS_32_UNSIGNED(x, first, last) | (0xffffffff << (31 - first))) : \
     BE_BITS_32_UNSIGNED(x, first, last))

/// Install and decode an instruction into the PoreInlineDissassembly object
///
/// \param dis A PoreInlineDisassembly structure to contain the disassembled
/// instruction.
///
/// \param instruction The initial (or only) 32 bits of a PORE instruction
///
/// For simplicity, instructions are currently (almost) fully decoded for all
/// possible formats. It is up to the application using this API to further
/// decode the actual opcode to determine which of these fields are valid for
/// the current instruction.
///
/// To simplify parity calculations the \a imd64 field is cleared here. A
/// companion API pore_inline_decode_imd64() is used to decode the final 64
/// bits of long instructions.
///
/// This API is designed to be called independently of the full disassembler,
/// in which case any fields of \a dis not explicitly set will be undefined.

void
vpore_inline_decode_instruction(PoreInlineDecode *dis, uint32_t instruction)
{
	dis->instruction = instruction;

	// Generic decoding
	dis->opcode	  = BE_BITS_32_UNSIGNED(instruction, 0, 6);
	dis->long_instruction = BE_BIT_32(instruction, 0);
	dis->parity	  = BE_BITS_32_UNSIGNED(instruction, 7, 7);
	dis->memory_space = BE_BIT_32(instruction, 8);
	dis->update	  = BE_BIT_32(instruction, 8);
	dis->capture	  = BE_BIT_32(instruction, 9);
	dis->imd16	  = BE_BITS_32_SIGNED(instruction, 16, 31);
	dis->scan_length  = BE_BITS_32_UNSIGNED(instruction, 16, 31);
	dis->imd20	  = BE_BITS_32_SIGNED(instruction, 12, 31);
	dis->imd24 = dis->ima24 = BE_BITS_32_UNSIGNED(instruction, 8, 31);
	dis->impco20	  = BE_BITS_32_SIGNED(instruction, 12, 31);
	dis->impco24	  = BE_BITS_32_SIGNED(instruction, 8, 31);
	dis->tR = dis->r0 = BE_BITS_32_UNSIGNED(instruction, 8, 11);
	dis->sR = dis->r1 = BE_BITS_32_UNSIGNED(instruction, 12, 15);
	dis->imd64	  = 0;

	// imA24 decoding
	if (dis->memory_space) {
		dis->base_register =
			BE_BIT_32(instruction, 9) ?
			PORE_OCI_MEMORY_BASE_ADDR1_ENC :
			PORE_OCI_MEMORY_BASE_ADDR0_ENC;

		dis->memory_offset =
			BE_BITS_32_UNSIGNED(dis->instruction, 10, 31);
	} else {
		dis->base_register =
			BE_BIT_32(instruction, 9) ?
			PORE_PRV_BASE_ADDR1_ENC :
			PORE_PRV_BASE_ADDR0_ENC;

		dis->pib_offset =
			BE_BITS_32_UNSIGNED(dis->instruction, 12, 31);
	}
}


/// Install and decode an imd64 into a PoreInlineDissassembly object
///
/// \param dis A PoreInlineDisassembly structure to contain the disassembled
/// data
///
/// \param imd64 The final 64 bits of a 12-byte PORE instruction
///
/// For simplicity, instructions are currently (almost) fully decoded for all
/// possible formats. It is up to the application to determine which if any of
/// these fields are valid for the current instruction.
///
/// This API is designed to be called independently of the full disassembler,
/// in which case any fields of \a dis not explicitly set will be undefined.

void
vpore_inline_decode_imd64(PoreInlineDecode *dis, uint64_t imd64)
{
	dis->imd64 = imd64;
	dis->impc48 = dis->imd64 & 0xffffffffffffull;
	dis->scan_select = imd64 >> 32;
	dis->scan_offset = imd64 & 0xffffffff;
}
OpenPOWER on IntegriCloud