Add partial support for 8-bit loads

We're big-endian.
when we have this in memory:

00 01 02 03

And we need the first byte, we load the first 16-bit word:

0x0001

The first byte is then in the upper part of the word, and requires
a right shift by 8.
So any load into an 8-bit typed container needs to shift stuff.

So far, stores from/to the stack are exempted, they always load/store
full 16-bit words.

And a few othe rminor things. Like string null terminators.
And escaped characters in character literals.

Can you believe it's spelled 'literal', with a single t?
Me neither.
This commit is contained in:
Paul Mathieu 2021-03-18 08:35:23 -07:00
parent 5612f23181
commit b70cdd13c4
4 changed files with 29 additions and 8 deletions

View File

@ -121,7 +121,11 @@ begin
end if;
regn_0 := to_integer(unsigned(load_reg(3 downto 0)));
reg_d(regn_0) <= mem_in;
if load_addr(0) = '1' then -- 8-bit load
reg_d(regn_0) <= mem_in(7 downto 0) & x"00";
else
reg_d(regn_0) <= mem_in;
end if;
when BRANCH =>
inst := x"0000"; -- NOP
reg_d(14) <= std_logic_vector(unsigned(reg_q(14)) + 2);

View File

@ -9,11 +9,11 @@ void init() {
}
int main() {
led0->output = 37;
init();
led0->output = 42;
while(1) {
led0->output = 42;
uint8_t c = uart_read(uart0);
uint16_t period;
if (c == 'c') {
@ -44,6 +44,8 @@ int main() {
period = 791; // B4, 493.88 Hz, maybe
uart_writen(uart0, "B4\r\n", 4);
led0->output = 64;
} else {
led0->output = 37;
}
square0->period = period;

View File

@ -145,7 +145,7 @@ struct_field: type IDENTIFIER sized_array* ";"
IDENTIFIER: /[_a-zA-Z]\w*/
COMMENT: /\/\/.*/
HEX_LITTERAL: /0x[a-fA-F0-9]+/
CHARACTER: /'[^']'/
CHARACTER: /'([^']|\\n|\\r|\\0|\\t)'/
%import common.WS

View File

@ -366,7 +366,7 @@ class CcTransform(lark.visitors.Transformer):
mul = _binary_op(lambda a, b: a*b)
shl = _binary_op(lambda a, b: a<<b)
CHARACTER = lambda _, x: ord(x[1])
CHARACTER = lambda _, x: ord(ast.literal_eval(x)[0])
IDENTIFIER = str
SIGNED_NUMBER = int
HEX_LITTERAL = lambda _, x: int(x[2:], 16)
@ -543,6 +543,20 @@ class Load(AsmOp):
def __init__(self, fun, ops):
self.fun = fun
self.dest, self.var = ops
fun.log(f'8bit load? {self.var.type} {self.is8bit}')
@property
def is8bit(self):
if not isinstance(self.var.type, PodType):
return False
if self.var.type.pod in ['uint8_t', 'int8_t', 'char']:
return True
return False
def _maybecast8bit(self, reg):
if self.is8bit:
return [f'shr {reg}, {reg}, 8']
return []
@property
def out(self):
@ -552,13 +566,13 @@ class Load(AsmOp):
reg = self.dest
if self.var.name in self.fun.locals:
src = self.var.stackaddr
return [f'load {reg}, [sp, {src}]']
return [f'load {reg}, [sp, {src}]'] # no 8bit cast to/from stack
elif self.var.addr_reg is not None:
return [f'load {reg}, [{self.var.addr_reg}]']
return [f'load {reg}, [{self.var.addr_reg}]'] + self._maybecast8bit(reg)
else:
return [f'set {reg}, {self.var.name}',
f'nop // in case we load a far global',
f'load {reg}, [{reg}]']
f'load {reg}, [{reg}]'] # unsure if we need a cast here
class Store(AsmOp):
scratch_need = 1
@ -1254,6 +1268,7 @@ def parse_tree(tree, debug=False):
for sym, dat in inte.strings.items():
out += [f'.global {sym}',
f'{sym}:']
dat += '\0'
if len(dat) % 2 != 0:
dat += '\0'
dat = dat.encode()