represent memory in c - c

I am trying to write an Instruction Set Simulator in C to simulate a machine running ARM.
I need to be able to represent 4GB memory efficiently and after some digging have come to the solution of creating an array of 1024 pointers each pointing to a block of 4MB which is dynamically allocated at its first use
#define MEMSIZE 1024 //1024 * 2Mb = 4Gb
#define PAGESIZE 4194304 //4 Mb
#define PAGEEXP 22 //2^PAGEEXP = PAGESIZE
uint32_t* mem[MEMSIZE];
My question is how do I access a certain address of memory?
What I have tried is breaking the address into index and offset as below but this seems to only return 0 for both index and offset. (memAdd is the address I am trying to access)
memIdx = memAdd >> PAGEEXP;
memOfs = memAdd & PAGESIZE;
the functions I use to read/write once I have the address are below:
void memWrite(uint32_t idx, uint32_t ofs, uint32_t val)
{
if(mem[idx] == 0)
mem[idx] = malloc(PAGESIZE);
*(mem[idx] + ofs) = *(mem[idx] + ofs) & val;
}
uint32_t memRead(uint32_t idx, uint32_t ofs)
{
if(mem[idx] == 0)
return 0;
else
return *(mem[idx] + ofs);
}
these seem right in my head however I am still not 100% comfortable with pointers so this may be wrong.
Sorry if this has already been discussed somewhere but I couldnt find anything relevent to what I need ( my keywords are pretty broad)

Start out looking at it logically instead of at the bit level.
You have pages of 4,194,304 bytes each.
Arithmetically, then, to turn a linear address into a (page, offset) pair, you divide by 4,194,304 to get the page number, and take the remainder to get the offset into the page.
page = address / PAGESIZE;
offset = address % PAGESIZE;
Since you want to do this efficiently and these are powers of 2, you can replace division by PAGESIZE with right-shift by the base-2 logarithm of PAGESIZE, which is 22:
page = address >> PAGEEXP;
So that part of your code is correct. However, what you want to do to get the offset is to mask out all but the bits you just shifted out of the page number. To do that, you have to AND with PAGESIZE - 1.
offset = address & (PAGESIZE - 1);
This is because in binary, what you're starting with is a number that looks like this (where p is a page number bit and o is an offset bit):
address = ppppppppppoooooooooooooooooooooo
You want to get the page number and the offset number by themselves. You clearly want to shift right by 22 bits to get the page number:
page = addresss >> 22 = 0000000000000000000000pppppppppp
But if you AND with the pagesize (00000000010000000000000000000000 in binary), you'll only have one at most one 1-bit in the answer, and it will just tell you if the page number is odd or even. Not useful.
What you want to AND with is instead one bit less than that, which is binary 00000000001111111111111111111111, thus:
ppppppppppoooooooooooooooooooooo
& 00000000001111111111111111111111
-----------------------------------
= 0000000000oooooooooooooooooooooo
which is how you get the offset.
This is a general rule: if N is an integer power of 2, then division by N is the same as right-shifting by log(N)/log(2), and the remainder of such a division is given by ANDing with (N-1).

If PAGESIZE is a power of 2, it has only 1 bit set. Hence AND-ing it with another value can only leave zero or one bit set in the result. Two possible values. But you're using it as an array index.
Also your memWrite(uint32_t idx, uint32_t ofs, uint32_t val) function always ANDs in the value of val. Hence for example if val is uint32_max any call to this function will have no effect.
Last, not only do you not check the result of malloc() for failure, you don't initialise the memory block which is returned.
Try an approach like this (unfortunately I have been unable to test it, I have no compiler handy just now).
enum { SIM_PAGE_BITS = 22 }; // 2^22 = 4MiB
enum { SIM_MEM_PAGES = 1024 }; // 1024 * 4MiB = 4GiB
enum { SIM_PAGE_SIZE = (1<<SIM_PAGE_BITS) };
enum { SIM_PAGE_MASK = SIM_PAGE_SIZE-1 };
enum { UNINITIALISED_MEMORY_CONTENT = 0 };
enum { WORD_BYTES = sizeof(uint32_t)/sizeof(unsigned char) };
#define PAGE_OFFSET(addr) (SIM_PAGE_MASK & (uint32_t)addr)
// cast to unsigned type to avoid sign extension surprises if addr<0
#define PAGE_NUM(addr) (((uint32_t)addr) >> SIM_PAGE_BITS)
#define IS_UNALIGNED(addr) (addr & (WORD_BYTES-1))
unsigned char* mem[MEMSIZE];
uint32_t memRead(uint32_t addr) {
if (IS_UNALIGNED(addr)) return handle_unaligned_read(addr);
const uint32_t page = PAGE_NUM(addr);
if (mem[page]) {
const unsigned char *p = mem[page] + PAGE_OFFSET(addr);
return *(uint32_t*)p;
} else {
return UNINITIALISED_MEMORY_CONTENT;
}
}
void memWrite(uint32_t addr, uint32_t val) {
if (IS_UNALIGNED(addr)) return handle_unaligned_write(addr, val);
const uint32_t page = PAGE_NUM(addr);
if (!mem[page]) {
if (val == UNINITIALISED_MEMORY_CONTENT) {
return;
}
mem[page] = malloc(SIM_PAGE_SIZE);
if (!mem[page]) {
handle_out_of_memory();
}
// If UNINITIALISED_MEMORY_CONTENT is always 0 we can
// use calloc instead of malloc then memset.
memset(mem[page], UNINITIALISED_MEMORY_CONTENT, SIM_PAGE_SIZE);
}
const unsigned char *p = mem[page] + PAGE_OFFSET(addr);
*(uint32_t*)p = val;
}

This will do what you want. I've used smaller sizes. I've left out the error checking for clarity. It uses your scheme of using an indexer array.
#include <cstdlib>
#include <cstdio>
#include <stdint.h>
#define NUMPAGE 1024
#define NUMINTSPERPAGE 4
uint32_t* buf;
uint32_t* idx[NUMPAGE];
void InitBuf()
{
buf = (uint32_t*) calloc(NUMPAGE, NUMINTSPERPAGE * sizeof uint32_t );
for ( size_t i = 0; i < NUMPAGE; i++ )
{
idx[i] = &buf[i * NUMINTSPERPAGE * sizeof uint32_t];
}
}
void memWrite(size_t i, size_t ofs, uint32_t val)
{
idx[i][ofs] = val;
}
uint32_t memRead(size_t i, size_t ofs)
{
return idx[i][ofs];
}
int main()
{
InitBuf();
uint32_t val = 1243;
memWrite(1, 2, val);
printf("difference = %ld", val - memRead(1, 2));
getchar();
}

I don't believe the value of memOfs is being calculated correctly. For instance, the decimal value 4194304 represented by PAGESIZE is 0x400000 in hexadecimal, which means that after the bitwise-AND operation, you're only getting bit 22 of the original address, not the lower 22 bits. Adding that value to the 4MB page-array-pointer actually sends you beyond the end of the allocated array on the heap. Change your mask for the offset calculation to 0x3FFFFF, and then bitwise-AND that with the original memory address in order to calculate the proper offset into the page. So for instance:
memIdx = memAdd >> PAGEEXP;
memOfs = memAdd & 0x3FFFFF; //value of memOfs will be between 0 and 4194303

Related

How to get the leftmost bits from Core Foundation CFDataRef?

I'm trying to get the N leftmost bits from a Core Foundation CFDataRef. New to CF and C, so here's what I've got so far. It's printing out 0, so something's off.
int get_N_leftmost_bits_from_data(int N)
{
// Create a CFDataRef from a 12-byte buffer
const unsigned char * _Nullable buffer = malloc(12);
const CFDataRef data = CFDataCreate(buffer, 12);
const unsigned char *_Nullable bytesPtr = CFDataGetBytePtr(data);
// Create a buffer for the underlying bytes
void *underlyingBytes = malloc(CFDataGetLength(data));
// Copy the first 4 bytes to underlyingBytes
memcpy(underlyingBytes, bytesPtr, 4);
// Convert underlying bytes to an int
int num = atoi(underlyingBytes);
// Shift all the needed bits right
const int numBitsInByte = 8;
const int shiftedNum = num >> ((4 * numBitsInByte) - N);
return shiftedNum;
}
Thank you for the help!
Since you're only concerned about the bit in the first four bytes, then you could just copy the bytes over to an integer then perform a bit-shift on that integer.
#include <string.h>
#include <stdint.h>
int main(){
uint8_t bytes[12] = {0};
for(int n = 0; n < sizeof(bytes) ; ++n){
bytes[n] = n+0xF;
//printf("%02x\n",bytes[n]);
}
uint32_t firstfour = 0;
//copy the first four bytes
memcpy(&firstfour,bytes,sizeof(uint32_t));
//get the left most bit
uint32_t bit = firstfour>>31&1;
return 0;
}
You can still perform memcpy in CF
In general, to get n leftmost bits from x, you have to do something like
x >> ((sizeof(x) * 8) - n) (I assume that byte consists of 8 bits)
I don't have access to apple's device and don't know its API but few remarks:
You don't define ret in your's supplied code. (and I don't think it is defined by apple's library)
I was not able to find CFNumberGetInt32() with my search engine and have no clue what it could do. Please post buildable code with enough context to understand it

Multiply two integers without using any arithmetic operators

I've managed to add and subtract two integers without using any arithmetic operators. I've tried multiply ways to multiply two integers together but can't seem to make any progress. How can I multiply two integers without using any arithmetic operators? The arithemtic operators you can't use are (+, ++, +=, -, --, -=, ∗, /, %). Also from the directions that were given is to "take lowest 16 bits of the product should be
stored in product, and the full product should be stored in full_product as a 32-bit value." The commented out lines in the method are there to show you what not to do. Thanks! Here is the code done in C
#include "alu.h"
/* Adds the two arguments and stores the sum in the return structure's result
* field. If the operation overflowed then the overflow flag is set. */
addition_subtraction_result add(uint16_t augend, uint16_t addend) {
addition_subtraction_result addition;
while (addend != 0){
int carry = augend & addend;
augend = augend ^ addend;
addend = carry << 1;
}
addition.result = augend;
//addition.overflow = false;
return addition;
}
/* Subtracts the second argument from the first, stores the difference in the
* return structure's result field. If the operation overflowed then the
* overflow flag is set. */
addition_subtraction_result subtract(uint16_t menuend, uint16_t subtrahend) {
addition_subtraction_result subtraction;
while (subtrahend != 0 ){
int borrow = (~menuend) & subtrahend;
menuend = menuend ^ subtrahend;
subtrahend = borrow << 1;
}
subtraction.result = menuend;
return subtraction;
}
/* Multiplies the two arguments. The function stores lowest 16 bits of the
* product in the return structure's product field and the full 32-bit product
* in the full_product field. If the product doesn't fit in the 16-bit
* product field then the overflow flag is set. */
multiplication_result multiply(uint16_t multiplicand, uint16_t multiplier) {
multiplication_result multiplication;
//multiplication.product = multiplicand * multiplier; // THIS IS DISALLOWED
//multiplication.full_product = multiplicand * multiplier; // THIS IS DISALLOWED
multiplication.product = multiplicand;
multiplication.full_product = multiplicand;
return multiplication;
}
General idea (types are deliberately incorrect to you can't copy/paste this back in):
uint16_t multiply(uint8_t multiplicand, uint8_t multiplier)
{
uint16_t result = 0;
for (int i = 0; i < CHAR_BIT * sizeof(multiplier); i++)
if (multiplier & (uint8_t))
result = add(result, (uint16_t)multiplicand << (uint16_t)i);
return result;
}
But this won't work for you yet because because you don't have long add yet. We need to decompose long add like this:
uint16_t addlong(uint8_t addend1a, uint8_t addend1b, uint8_t addend2a, uint8_t addend2b)
{
struct addend_result a = add(addend1a, addend2a);
struct addend_result b = add(addend2a, addend2b);
if (a.carry) b = add(b.result, 1);
return a.result | ((uint16_t)b.result << 8);
}
So these are the pieces required to build. Adapt them to the framework you actually have and the type widths you actually have.
You have to unroll the for loop in multiply because of silliness. This means you get 16 lines because your input size is 16 bits.

Get list of bits set in BitMap

In C, Is there any optimized way of retrieving list of BitPositions set without parsing through each bit.
Consider following example
int bitmap[4];
So, there are 4 * 32 Bit Positions..Values are following
bitmap = { 0x1, 0x0, 0x0, 0x0010001 }
I want retrieve Position of each bit set instead of parsing from 0 to 4 * 32 positions.
First of all, one cannot really use int for bitmap in C, because shifting a bit to left to the sign bit has undefined behaviour, C doesn't guarantee that the representation is two's complement, or that there are 32 bits in an int; that being said the easiest way to avoid these pitfalls is to use the uint32_t from <stdint.h> instead. Thus
#include <stdint.h>
uint32_t bitmap[4];
So consider that you number these bits 0 ... 127 from indexes 0 ... 3; and within indexes 0 ... 31; so, you can get the index into array and the bit number within that value by using the following formula:
int bit_number = // a value from 0 ... 127
int index = value >> 32; // shift right by number of bits in each index
int bit_in_value = value & 31; // take modulo 32 to get the bit in value
Now you can index the integer by:
bitmap[index];
and the bit mask for the desired value is
uint32_t mask = (uint32_t)1 << bit_in_value;
so you can check if the bit is set by doing
bit_is_set = !!(bitmap[index] & mask);
Now to speed things up, you can skip any index for which bitmap[index] is 0 because it doesn't contain any bits set; likewise, within each index you can speed things up by shifting bits in the uint32_t from the bitmap right by 1 and masking with 1; and breaking the loop when the uint32_t becomes 0:
for (int index = 0; index <= 3; index ++) {
uint32_t entry = bitmap[index];
if (! entry) {
continue;
}
int bit_number = 32 * index;
while (entry) {
if (entry & 1) {
printf("bit number %d is set\n", bit_number);
}
entry >>= 1;
bit_number ++;
}
}
Other than that there is not much to speed up, besides lookup tables, or using compiler intrinsics, such as this to set which is the lowest bit set but you'd still have to use some anyway.
An optimal solution which runs in O(k), where k = the total number of set bits in your entire list, can be achieved by using a lookup table. For example, you can use a table of 256 entries to describe the bit positions of every set bit in that byte. The index would be the actual value of the Byte.
For each entry you could use the following structure.
struct
{
int numberOfSetBits;
char* list; // use malloc and alloocate the list according to numberOfSetBits
}
You can then iterate across the list member of each structure and the number of iterations = the number of set bits for that byte. For a 32-bit integer you will have to iterate through 4 of these structs, one per each byte. To determine which entry you need to check you use a Bitmap and shift 8 bits. Note, that the bit positions are relative to that byte, so you may have to add an offset or either 24, 16, or 8 depending on the byte you are iterating through (assuming a 32 bit integer).
Note: if additional memory usage is not a problem for you, you could build a 64K Table of 16-bit entries and you will decrease the number of your structs by half.
Related with this question, you can see What is the fastest way to return the positions of all set bits in a 64-bit integer?
A simple solution, but perhaps not the fastest, depending on the times of the log and pow functions:
#include<math.h>
#include<stdio.h>
void getSetBits(unsigned int num, int offset){
int bit;
while(num){
bit = log2(num);
num -= pow(2, bit);
printf("%i\n", offset + bit); // use bit number
}
}
int main(){
int i, bitmap[4] = {0x1, 0x0, 0x0, 0x0010001};
for(i = 0; i < 4; i++)
getSetBits(bitmap[i], i * 32);
}
Complexity O(D) | D is the number of set bits.

Pointer type of smaller size than variable

Working with embedded systems, in order to have more resolution in a incremental sequence, I have two variables, one always following the other.
Specifically, I set a goal value using a 8 bits variable, but to go from one point (current value) to another I do it using 32 bits steps.
For example (that is a stupid example, but it just to show how I want to use it, in my code there are some temporizations which require the 32 bits varaibles to allow a slow change):
/* The variables */
char goal8bits; // 8 bits
long int current32bits; // 32 bits
char current8bits; // 8 bits
long int step32bits; // 32 bits
/* The main function (in the real code that is done periodically with a specific period) */
current32bits = CONVERT_8BITS_TO_32BITS(current8bits); // E.g: 0xAB -> 0xABABABAB
if (goal8bits < current8bits) {
current32bits += step32bits;
}
current8bits = CONVERT_32BITS_TO_8BITS(current32bits); // E.g: 0x01234567 -> 0x01
/* Other parts of the code */
I use current8bits to know the current value in the middle of a transition.
My question is if I can use a char pointer and make it point to the 32 bits variable one, so I do not need to update it each time I change it.
The previous example will look like this:
/* The variables */
char goal8bits; // 8 bits
long int current32bits; // 32 bits
char *current8bits = (char *)&current32bits; // Pointer to 8 bits
long int step32bits; // 32 bits
/* The main function (in the real code that is done periodically with a specific period) */
if (goal8bits < *current8bits) {
current32bits += step32bits;
}
/* Other parts of the code */
I will use *current8bits to know the current value in the middle of a transition.
Do you see any problem in doing that? Can it lead to a problem wih endianism?
Thank you!
If you know the endianless of your system, and it is static you have to select from
char *current8bits = (char *)&current32bits;
or
char *current8bits = (((char *)&current32bits)+3);
If you have to test it, and your system cannot give you such of info you can derive it at application startup
uint32_t temp = 0x01020304;
uint8_t *temp2 = (uint8_t *)(&temp);
if (*temp2 == 0x01)
{
char *current8bits = (char *)&current32bits;
}
else
{
char *current8bits = (((char *)&current32bits)+3);
}
Another good solution is the top-voted and checked-as-answered answer HERE.
Yes, it is endian dependent code, to make it portable you can use a mask and the left shift operator:
uint8_t goal8bits = 0x01; // 8 bits
uint32_t current32bits = 0x01234567; // 32 bits
uint32_t step32bits = 1; // 32 bits
if (goal8bits < ((current32bits & 0xFF000000) >> 24)) {
current32bits += step32bits;
}

What is the fastest way for calculating the sum of arbitrary large binary numbers

I can't seem to find any good literature about this. Having a BigBinaryNumber (two's complement with virtual sign bit) structure like this:
typedef unsigned char byte;
enum Sign {NEGATIVE = (-1), ZERO = 0, POSITIVE = 1};
typedef enum Sign Sign;
struct BigBinaryNumber
{
byte *number;
Sign signum;
unsigned int size;
};
typedef struct BigBinaryNumber BigBinaryNumber;
I could just go for the elementary school approach (i.e. summing individual bytes and using the carry for subsequent summing) or perhaps work with a fixed size look-up table.
Is there any good literature about the fastest method for binary summation?
The fastest method for adding numbers is your processor's existing add instruction. So long as you've got the number laid out sensibly in memory (e.g, you don't have the bit order backwards or anything), it should be pretty straightforward to load 32 bits at a time from each number, add them together natively, and get the carry:
uint32_t *word_1 = &number1.number + offset, *word_2 = &number2.number + offset;
uint32_t *word_tgt = &dest.number + offset;
uint64_t sum = *word_1 + *word_2 + carry; // note the type!
*word_tgt = (uint32_t) sum; // truncate
carry = sum >> 32;
Note that you might have to add some special cases for dealing with the last byte in the number (or make sure that *number always has a multiple of 4 bytes allocated).
If you're using a 64-bit CPU, you may be able to extend this to work with uint64_t. There's no uint128_t for the overflow, though, so you might have to use some trickery to get the carry bit.
The "trick" is to use the native (or maybe larger) integer size.
#duskwuff is on the money to walk through number, multiple bytes at a time.
As with all "What is the fastest way ...", candidate solutions should be profiled.
Follows is a one type solution so one could use the largest type as well, the native type or any 1 type. e.g. uintmax_t or unsigned. The carry is partiality handled via code and carry generation depends on testing if addition will overflow.
typedef unsigned MyInt;
#define MyInt_MAX UINT_MAX
void Add(BigBinaryNumber *a, BigBinaryNumber *b, BigBinaryNumber *sum) {
// Assume same size for a, b, sum.
// Assume memory allocated for sum.
// Assume a->size is a multiple of sizeof(MyInt);
// Assume a->number endian is little and matches platform endian.
// Assume a->alignment matches MyInt alignment.
unsigned int size = a->size;
MyInt* ap = a->number;
MyInt* bp = b->number;
MyInt* sump = sum->number;
int carry = 0;
while (size > 0) {
size -= sizeof(MyInt);
if (carry) {
if (*ap <= (MyInt_MAX - 1 - *bp)) {
carry = 0;
}
*sump++ = *ap++ + *bp++ + 1;
}
else {
if (*ap > (MyInt_MAX - *bp)) {
carry = 1;
}
*sump++ = *ap++ + *bp++;
}
} // end while
// Integer overflow/underflow handling not shown,
// but depend on carry, and the sign of a, b
// Two's complement sign considerations not shown.
}

Resources