debuggers: import openocd-0.7.0
Initial check-in of openocd-0.7.0 as it can be downloaded from http://sourceforge.net/projects/openocd/files/openocd/0.7.0/ Any modifications will follow. Change-Id: I6949beaefd589e046395ea0cb80f4e1ab1654d55
This commit is contained in:
380
debuggers/openocd/jimtcl/jim-pack.c
Normal file
380
debuggers/openocd/jimtcl/jim-pack.c
Normal file
@ -0,0 +1,380 @@
|
||||
#include <string.h>
|
||||
#include <jim.h>
|
||||
|
||||
/* Provides the [pack] and [unpack] commands to pack and unpack
|
||||
* a binary string to/from arbitrary width integers and strings.
|
||||
*
|
||||
* This may be used to implement the [binary] command.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Big endian bit test.
|
||||
*
|
||||
* Considers 'bitvect' as a big endian bit stream and returns
|
||||
* bit 'b' as zero or non-zero.
|
||||
*/
|
||||
static int JimTestBitBigEndian(const unsigned char *bitvec, int b)
|
||||
{
|
||||
div_t pos = div(b, 8);
|
||||
return bitvec[pos.quot] & (1 << (7 - pos.rem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Little endian bit test.
|
||||
*
|
||||
* Considers 'bitvect' as a little endian bit stream and returns
|
||||
* bit 'b' as zero or non-zero.
|
||||
*/
|
||||
static int JimTestBitLittleEndian(const unsigned char *bitvec, int b)
|
||||
{
|
||||
div_t pos = div(b, 8);
|
||||
return bitvec[pos.quot] & (1 << pos.rem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign extends the given value, 'n' of width 'width' bits.
|
||||
*
|
||||
* For example, sign extending 0x80 with a width of 8, produces -128
|
||||
*/
|
||||
static jim_wide JimSignExtend(jim_wide n, int width)
|
||||
{
|
||||
if (width == sizeof(jim_wide) * 8) {
|
||||
/* Can't sign extend the maximum size integer */
|
||||
return n;
|
||||
}
|
||||
if (n & ((jim_wide)1 << (width - 1))) {
|
||||
/* Need to extend */
|
||||
n -= ((jim_wide)1 << width);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Big endian integer extraction.
|
||||
*
|
||||
* Considers 'bitvect' as a big endian bit stream.
|
||||
* Returns an integer of the given width (in bits)
|
||||
* starting at the given position (in bits).
|
||||
*
|
||||
* The pos/width must represent bits inside bitvec,
|
||||
* and the width be no more than the width of jim_wide.
|
||||
*/
|
||||
static jim_wide JimBitIntBigEndian(const unsigned char *bitvec, int pos, int width)
|
||||
{
|
||||
jim_wide result = 0;
|
||||
int i;
|
||||
|
||||
/* Aligned, byte extraction */
|
||||
if (pos % 8 == 0 && width % 8 == 0) {
|
||||
for (i = 0; i < width; i += 8) {
|
||||
result = (result << 8) + bitvec[(pos + i) / 8];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Unaligned */
|
||||
for (i = 0; i < width; i++) {
|
||||
if (JimTestBitBigEndian(bitvec, pos + width - i - 1)) {
|
||||
result |= ((jim_wide)1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Little endian integer extraction.
|
||||
*
|
||||
* Like JimBitIntBigEndian() but considers 'bitvect' as a little endian bit stream.
|
||||
*/
|
||||
static jim_wide JimBitIntLittleEndian(const unsigned char *bitvec, int pos, int width)
|
||||
{
|
||||
jim_wide result = 0;
|
||||
int i;
|
||||
|
||||
/* Aligned, byte extraction */
|
||||
if (pos % 8 == 0 && width % 8 == 0) {
|
||||
for (i = 0; i < width; i += 8) {
|
||||
result += (jim_wide)bitvec[(pos + i) / 8] << i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Unaligned */
|
||||
for (i = 0; i < width; i++) {
|
||||
if (JimTestBitLittleEndian(bitvec, pos + i)) {
|
||||
result |= ((jim_wide)1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Big endian bit set.
|
||||
*
|
||||
* Considers 'bitvect' as a big endian bit stream and sets
|
||||
* bit 'b' to 'bit'
|
||||
*/
|
||||
static void JimSetBitBigEndian(unsigned char *bitvec, int b, int bit)
|
||||
{
|
||||
div_t pos = div(b, 8);
|
||||
if (bit) {
|
||||
bitvec[pos.quot] |= (1 << (7 - pos.rem));
|
||||
}
|
||||
else {
|
||||
bitvec[pos.quot] &= ~(1 << (7 - pos.rem));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Little endian bit set.
|
||||
*
|
||||
* Considers 'bitvect' as a little endian bit stream and sets
|
||||
* bit 'b' to 'bit'
|
||||
*/
|
||||
static void JimSetBitLittleEndian(unsigned char *bitvec, int b, int bit)
|
||||
{
|
||||
div_t pos = div(b, 8);
|
||||
if (bit) {
|
||||
bitvec[pos.quot] |= (1 << pos.rem);
|
||||
}
|
||||
else {
|
||||
bitvec[pos.quot] &= ~(1 << pos.rem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Big endian integer packing.
|
||||
*
|
||||
* Considers 'bitvect' as a big endian bit stream.
|
||||
* Packs integer 'value' of the given width (in bits)
|
||||
* starting at the given position (in bits).
|
||||
*
|
||||
* The pos/width must represent bits inside bitvec,
|
||||
* and the width be no more than the width of jim_wide.
|
||||
*/
|
||||
static void JimSetBitsIntBigEndian(unsigned char *bitvec, jim_wide value, int pos, int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Common fast option */
|
||||
if (pos % 8 == 0 && width == 8) {
|
||||
bitvec[pos / 8] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < width; i++) {
|
||||
int bit = !!(value & ((jim_wide)1 << i));
|
||||
JimSetBitBigEndian(bitvec, pos + width - i - 1, bit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Little endian version of JimSetBitsIntBigEndian()
|
||||
*/
|
||||
static void JimSetBitsIntLittleEndian(unsigned char *bitvec, jim_wide value, int pos, int width)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Common fast option */
|
||||
if (pos % 8 == 0 && width == 8) {
|
||||
bitvec[pos / 8] = value;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < width; i++) {
|
||||
int bit = !!(value & ((jim_wide)1 << i));
|
||||
JimSetBitLittleEndian(bitvec, pos + i, bit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [unpack]
|
||||
*
|
||||
* Usage: unpack binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth
|
||||
*
|
||||
* Unpacks bits from $binvalue at bit position $bitpos and with $bitwidth.
|
||||
* Interprets the value according to the type and returns it.
|
||||
*/
|
||||
static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
int option;
|
||||
static const char * const options[] = { "-intbe", "-intle", "-uintbe", "-uintle", "-str", NULL };
|
||||
enum { OPT_INTBE, OPT_INTLE, OPT_UINTBE, OPT_UINTLE, OPT_STR, };
|
||||
jim_wide pos;
|
||||
jim_wide width;
|
||||
|
||||
if (argc != 5) {
|
||||
Jim_WrongNumArgs(interp, 1, argv, "binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth");
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
if (Jim_GetWide(interp, argv[3], &pos) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (Jim_GetWide(interp, argv[4], &width) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
if (option == OPT_STR) {
|
||||
int len;
|
||||
const char *str = Jim_GetString(argv[1], &len);
|
||||
|
||||
if (width % 8 || pos % 8) {
|
||||
Jim_SetResultString(interp, "string field is not on a byte boundary", -1);
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
if (pos >= 0 && width > 0 && pos < len * 8) {
|
||||
if (pos + width > len * 8) {
|
||||
width = len * 8 - pos;
|
||||
}
|
||||
Jim_SetResultString(interp, str + pos / 8, width / 8);
|
||||
}
|
||||
return JIM_OK;
|
||||
}
|
||||
else {
|
||||
int len;
|
||||
const unsigned char *str = (const unsigned char *)Jim_GetString(argv[1], &len);
|
||||
jim_wide result = 0;
|
||||
|
||||
if (width > sizeof(jim_wide) * 8) {
|
||||
Jim_SetResultFormatted(interp, "int field is too wide: %#s", argv[4]);
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
if (pos >= 0 && width > 0 && pos < len * 8) {
|
||||
if (pos + width > len * 8) {
|
||||
width = len * 8 - pos;
|
||||
}
|
||||
if (option == OPT_INTBE || option == OPT_UINTBE) {
|
||||
result = JimBitIntBigEndian(str, pos, width);
|
||||
}
|
||||
else {
|
||||
result = JimBitIntLittleEndian(str, pos, width);
|
||||
}
|
||||
if (option == OPT_INTBE || option == OPT_INTLE) {
|
||||
result = JimSignExtend(result, width);
|
||||
}
|
||||
}
|
||||
Jim_SetResultInt(interp, result);
|
||||
return JIM_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [pack]
|
||||
*
|
||||
* Usage: pack varname value -intle|-intbe|-str width ?bitoffset?
|
||||
*
|
||||
* Packs the binary representation of 'value' into the variable of the given name.
|
||||
* The value is packed according to the given type, width and bitoffset.
|
||||
* The variable is created if necessary (like [append])
|
||||
* Ihe variable is expanded if necessary
|
||||
*/
|
||||
static int Jim_PackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
int option;
|
||||
static const char * const options[] = { "-intle", "-intbe", "-str", NULL };
|
||||
enum { OPT_LE, OPT_BE, OPT_STR };
|
||||
jim_wide pos = 0;
|
||||
jim_wide width;
|
||||
jim_wide value;
|
||||
Jim_Obj *stringObjPtr;
|
||||
int len;
|
||||
int freeobj = 0;
|
||||
|
||||
if (argc != 5 && argc != 6) {
|
||||
Jim_WrongNumArgs(interp, 1, argv, "varName value -intle|-intbe|-str bitwidth ?bitoffset?");
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (Jim_GetEnum(interp, argv[3], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (option != OPT_STR && Jim_GetWide(interp, argv[2], &value) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (Jim_GetWide(interp, argv[4], &width) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (width <= 0 || (option == OPT_STR && width % 8) || (option != OPT_STR && width > sizeof(jim_wide) * 8)) {
|
||||
Jim_SetResultFormatted(interp, "bad bitwidth: %#s", argv[5]);
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (argc == 6) {
|
||||
if (Jim_GetWide(interp, argv[5], &pos) != JIM_OK) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
if (pos < 0 || (option == OPT_STR && pos % 8)) {
|
||||
Jim_SetResultFormatted(interp, "bad bitoffset: %#s", argv[5]);
|
||||
return JIM_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
|
||||
if (!stringObjPtr) {
|
||||
/* Create the string if it doesn't exist */
|
||||
stringObjPtr = Jim_NewEmptyStringObj(interp);
|
||||
freeobj = 1;
|
||||
}
|
||||
else if (Jim_IsShared(stringObjPtr)) {
|
||||
freeobj = 1;
|
||||
stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr);
|
||||
}
|
||||
|
||||
len = Jim_Length(stringObjPtr) * 8;
|
||||
|
||||
/* Extend the string as necessary first */
|
||||
while (len < pos + width) {
|
||||
Jim_AppendString(interp, stringObjPtr, "", 1);
|
||||
len += 8;
|
||||
}
|
||||
|
||||
Jim_SetResultInt(interp, pos + width);
|
||||
|
||||
/* Now set the bits. Note that the the string *must* have no non-string rep
|
||||
* since we are writing the bytes directly.
|
||||
*/
|
||||
Jim_AppendString(interp, stringObjPtr, "", 0);
|
||||
|
||||
if (option == OPT_BE) {
|
||||
JimSetBitsIntBigEndian((unsigned char *)stringObjPtr->bytes, value, pos, width);
|
||||
}
|
||||
else if (option == OPT_LE) {
|
||||
JimSetBitsIntLittleEndian((unsigned char *)stringObjPtr->bytes, value, pos, width);
|
||||
}
|
||||
else {
|
||||
pos /= 8;
|
||||
width /= 8;
|
||||
|
||||
if (width > Jim_Length(argv[2])) {
|
||||
width = Jim_Length(argv[2]);
|
||||
}
|
||||
memcpy(stringObjPtr->bytes + pos, Jim_GetString(argv[2], NULL), width);
|
||||
/* No padding is needed since the string is already extended */
|
||||
}
|
||||
|
||||
if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) {
|
||||
if (freeobj) {
|
||||
Jim_FreeNewObj(interp, stringObjPtr);
|
||||
return JIM_ERR;
|
||||
}
|
||||
}
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
int Jim_packInit(Jim_Interp *interp)
|
||||
{
|
||||
if (Jim_PackageProvide(interp, "pack", "1.0", JIM_ERRMSG)) {
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
Jim_CreateCommand(interp, "unpack", Jim_UnpackCmd, NULL, NULL);
|
||||
Jim_CreateCommand(interp, "pack", Jim_PackCmd, NULL, NULL);
|
||||
return JIM_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user