ps5: various errata; it works!!

This commit is contained in:
2026-04-01 21:37:58 +02:00
parent e01baf43c6
commit c7d61a5411
+26 -9
View File
@@ -135,8 +135,8 @@ static void generate_function(symbol_t* function)
symbol_t *sym = symtable->symbols[i];
switch (sym->type) {
case SYMBOL_PARAMETER:
if (i < NUM_REGISTER_PARAMS) {
PUSHQ(REGISTER_PARAMS[i]);
if (sym->sequence_number < NUM_REGISTER_PARAMS) {
PUSHQ(REGISTER_PARAMS[sym->sequence_number]);
} else {
/* these params are already on the stack */;
}
@@ -177,6 +177,10 @@ static void generate_function_call(node_t* call)
POPQ(REGISTER_PARAMS[i]);
}
CALL(call->children[0]->symbol->name);
if (args->n_children > NUM_REGISTER_PARAMS) {
int stack_args = args->n_children - NUM_REGISTER_PARAMS;
EMIT("addq $%d, %s", stack_args * 8, RSP);
}
}
#define UNARY_OP(OP, INST) \
@@ -189,7 +193,8 @@ static void generate_function_call(node_t* call)
generate_expression(left); \
PUSHQ(RAX); \
generate_expression(right); \
POPQ(RCX); \
MOVQ(RAX, RCX); \
POPQ(RAX); \
INST(RCX, RAX); \
}
#define DIVISION_OP \
@@ -238,7 +243,12 @@ static void generate_expression(node_t* expression)
switch (expression->n_children) {
case 1:
UNARY_OP("-", NEGQ);
/* logical not "!" is omitted */
if (strcmp(op, "!") == 0) {
generate_expression(expression->children[0]);
CMPQ("$0", RAX);
SETE(AL);
MOVZBQ(AL, RAX);
}
break;
case 2:
node_t *left = expression->children[0];
@@ -269,19 +279,24 @@ static void generate_expression(node_t* expression)
static void generate_base_address(node_t *identifier) {
assert(identifier->type == IDENTIFIER);
symbol_t *sym = identifier->symbol;
int offset;
switch (sym->type) {
case SYMBOL_GLOBAL_VAR:
case SYMBOL_GLOBAL_ARRAY:
LEAQ_GLOBAL(sym->name, RAX);
break;
case SYMBOL_LOCAL_VAR:
int offset = -8 * (sym->sequence_number - FUNC_PARAM_COUNT(current_function) + 6 + 1);
int spill = FUNC_PARAM_COUNT(current_function) > NUM_REGISTER_PARAMS
? NUM_REGISTER_PARAMS : FUNC_PARAM_COUNT(current_function);
int local_index = sym->sequence_number - FUNC_PARAM_COUNT(current_function);
offset = -8 * (spill + local_index + 1);
LEAQ_OFFSET(offset, RBP, RAX);
break;
case SYMBOL_PARAMETER:
if (FUNC_PARAM_COUNT(current_function) < NUM_REGISTER_PARAMS) {
int offset = -8 * (sym->sequence_number + 1);
if (sym->sequence_number < NUM_REGISTER_PARAMS) {
offset = -8 * (sym->sequence_number + 1);
} else {
int offset = 8 * (sym->sequence_number - 6 + 2);
offset = 8 * (sym->sequence_number - 6 + 2);
}
LEAQ_OFFSET(offset, RBP, RAX);
break;
@@ -299,7 +314,7 @@ static void generate_assignment_statement(node_t* statement)
if (child->type == IDENTIFIER) {
generate_expression(statement->children[1]);
STASH();
generate_base_address(child->children[0]);
generate_base_address(child);
EMIT("movq %s, (%s)", RCX, RAX);
} else if (child->type == ARRAY_INDEXING) {
generate_base_address(child->children[0]);
@@ -307,7 +322,9 @@ static void generate_assignment_statement(node_t* statement)
generate_expression(child->children[1]);
POPQ(RCX);
EMIT("leaq (%s, %s, 8), %s", RCX, RAX, RCX);
PUSHQ(RCX);
generate_expression(statement->children[1]);
POPQ(RCX);
EMIT("movq %s, (%s)", RAX, RCX); // save the value in rax to the address of identifier[index]
}
}