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:
parent
5612f23181
commit
b70cdd13c4
@ -121,7 +121,11 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
regn_0 := to_integer(unsigned(load_reg(3 downto 0)));
|
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 =>
|
when BRANCH =>
|
||||||
inst := x"0000"; -- NOP
|
inst := x"0000"; -- NOP
|
||||||
reg_d(14) <= std_logic_vector(unsigned(reg_q(14)) + 2);
|
reg_d(14) <= std_logic_vector(unsigned(reg_q(14)) + 2);
|
||||||
|
@ -9,11 +9,11 @@ void init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
led0->output = 37;
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
led0->output = 42;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
led0->output = 42;
|
|
||||||
uint8_t c = uart_read(uart0);
|
uint8_t c = uart_read(uart0);
|
||||||
uint16_t period;
|
uint16_t period;
|
||||||
if (c == 'c') {
|
if (c == 'c') {
|
||||||
@ -44,6 +44,8 @@ int main() {
|
|||||||
period = 791; // B4, 493.88 Hz, maybe
|
period = 791; // B4, 493.88 Hz, maybe
|
||||||
uart_writen(uart0, "B4\r\n", 4);
|
uart_writen(uart0, "B4\r\n", 4);
|
||||||
led0->output = 64;
|
led0->output = 64;
|
||||||
|
} else {
|
||||||
|
led0->output = 37;
|
||||||
}
|
}
|
||||||
|
|
||||||
square0->period = period;
|
square0->period = period;
|
||||||
|
@ -145,7 +145,7 @@ struct_field: type IDENTIFIER sized_array* ";"
|
|||||||
IDENTIFIER: /[_a-zA-Z]\w*/
|
IDENTIFIER: /[_a-zA-Z]\w*/
|
||||||
COMMENT: /\/\/.*/
|
COMMENT: /\/\/.*/
|
||||||
HEX_LITTERAL: /0x[a-fA-F0-9]+/
|
HEX_LITTERAL: /0x[a-fA-F0-9]+/
|
||||||
CHARACTER: /'[^']'/
|
CHARACTER: /'([^']|\\n|\\r|\\0|\\t)'/
|
||||||
|
|
||||||
|
|
||||||
%import common.WS
|
%import common.WS
|
||||||
|
23
tools/cc.py
23
tools/cc.py
@ -366,7 +366,7 @@ class CcTransform(lark.visitors.Transformer):
|
|||||||
mul = _binary_op(lambda a, b: a*b)
|
mul = _binary_op(lambda a, b: a*b)
|
||||||
shl = _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
|
IDENTIFIER = str
|
||||||
SIGNED_NUMBER = int
|
SIGNED_NUMBER = int
|
||||||
HEX_LITTERAL = lambda _, x: int(x[2:], 16)
|
HEX_LITTERAL = lambda _, x: int(x[2:], 16)
|
||||||
@ -543,6 +543,20 @@ class Load(AsmOp):
|
|||||||
def __init__(self, fun, ops):
|
def __init__(self, fun, ops):
|
||||||
self.fun = fun
|
self.fun = fun
|
||||||
self.dest, self.var = ops
|
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
|
@property
|
||||||
def out(self):
|
def out(self):
|
||||||
@ -552,13 +566,13 @@ class Load(AsmOp):
|
|||||||
reg = self.dest
|
reg = self.dest
|
||||||
if self.var.name in self.fun.locals:
|
if self.var.name in self.fun.locals:
|
||||||
src = self.var.stackaddr
|
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:
|
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:
|
else:
|
||||||
return [f'set {reg}, {self.var.name}',
|
return [f'set {reg}, {self.var.name}',
|
||||||
f'nop // in case we load a far global',
|
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):
|
class Store(AsmOp):
|
||||||
scratch_need = 1
|
scratch_need = 1
|
||||||
@ -1254,6 +1268,7 @@ def parse_tree(tree, debug=False):
|
|||||||
for sym, dat in inte.strings.items():
|
for sym, dat in inte.strings.items():
|
||||||
out += [f'.global {sym}',
|
out += [f'.global {sym}',
|
||||||
f'{sym}:']
|
f'{sym}:']
|
||||||
|
dat += '\0'
|
||||||
if len(dat) % 2 != 0:
|
if len(dat) % 2 != 0:
|
||||||
dat += '\0'
|
dat += '\0'
|
||||||
dat = dat.encode()
|
dat = dat.encode()
|
||||||
|
Loading…
Reference in New Issue
Block a user